home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / wdwmanag.i < prev    next >
Text File  |  1997-10-26  |  124KB  |  4,057 lines

  1. IMPLEMENTATION MODULE WdwManager;
  2.  
  3. (*==============================================================*
  4.  * Modul:               WdwManager - Window-Verwaltung fr      *
  5.  *                      alle Module                             *
  6.  * Autor:               Dirk Steins                             *
  7.  * erstellt am:         3.4.1992                                *
  8.  * letzte Žnderung am:  29.6.1993                               *
  9.  * Version:             0.7                                     *
  10.  * Interne Version:     V#0004                                  *
  11.  *==============================================================*
  12.  
  13.  *----------------------------------------------------------------------------
  14.  * Datum    Vers. Autor Žnderung (Arbeitsbericht)                            
  15.  *----------------------------------------------------------------------------
  16.  *
  17.  * 12.4.92  0.35  DS    Tastaturclick jetzt ausgeschaltet mit nur
  18.  *                      noch zwei SupExecs. Das ganze ist trotzdem 
  19.  *                      unsauber, da auf fremden Speicher zugegriffen wird.
  20.  *                      In zuknftigen Versionen muž man dann mal sehen, was 
  21.  *                      MultiTOS mit Memory Protection dazu sagen wird.
  22.  * 4.12.92  0.4   DS    Anpassung an WMBOTTOMED
  23.  * 9.12.92  0.45  DS    Bei mehr als zwei Fenstern funktionierte WFBOTTOMED 
  24.  *                      nicht richtig. Behoben
  25.  * 23.5.93  0.5   DS    Anpassung an Atari Nachrichtennummer fr WFBOTTOMED
  26.  * 15.6.93  0.6   DS    Anpassung an erweiterte Scrollfunktionen von WINX   
  27.  * 29.6.93  0.7   DS    Anpassung an Iconify und andere Sachen in AES 4.1. 
  28.  *                      Tastaturrepeat ber SupExecs ist schon l„nger wieder 
  29.  *                      draužen
  30.  *
  31.  *
  32.  *
  33.  *----------------------------------------------------------------------------
  34.  *)
  35.  
  36. (*$Z+*)
  37.  
  38. FROM SYSTEM     IMPORT LOC, ADDRESS, ADR, LONGWORD, CALLSYS, CADR;
  39.  
  40. FROM GrafBase   IMPORT Rectangle, LongRect;
  41.  
  42. FROM Storage    IMPORT ALLOCATE, DEALLOCATE;
  43.  
  44. IMPORT BinOps, Strings;
  45.  
  46. IMPORT MagicSys, MagicAES, MagicVDI, MagicXBIOS, MagicDOS, MagicCookie;
  47.  
  48. IMPORT mtAppl, mtUtils;
  49.  
  50. IMPORT Mintbind;
  51.  
  52. FROM MagicVDI    IMPORT VDIIntIn, VDIPtsIn, VDIControl;
  53.  
  54. FROM Void       IMPORT v;
  55.  
  56. IMPORT RectFuncs;
  57.  
  58. IMPORT StrConv;
  59.  
  60. CONST
  61.         minWindWidth  = 80;
  62.         minWindHeight = 80;
  63.  
  64. (* Typdefinition *)
  65. TYPE
  66.         ptrWdwSlot      = POINTER TO wdwSlot;
  67.  
  68.         wdwSlot         = RECORD
  69.                             wdw       : INTEGER;        (* Window-Handle               *)
  70.                             vdi       : INTEGER;        (* VDI-Workstation fr Fenster *)
  71.                             used,
  72.                             isFull,
  73.                             isTop,
  74.                             isHidden,
  75.                             isIcon    : BOOLEAN;
  76.                             wdwLast,
  77.                             wdwCurr,
  78.                             wdwIcon,
  79.                             wdwWork,
  80.                             wdwFull   : Rectangle;
  81.                             document  : LongRect;
  82.                             xFactor,
  83.                             yFactor   : LONGINT;       (* Multiplikatoren fr Document-Struktur *)
  84.                             pageW,
  85.                             pageH     : LONGINT;       (* Breite und H”he einer Seite in Einheiten *)
  86.                             minScrollW,
  87.                             minScrollH: LONGINT;       (* Um diesen Betrag wird beim Zeilenweise scrollen gescrollt *)
  88.                             pixOff    : INTEGER;       (* Offset am linken Fensterrand in Pixeln *)
  89.                             snap      : BOOLEAN;        (* Snap on Font-Size *)
  90.                             comps     : BITSET;
  91.                             wdwInfo   : ARRAY [0..139] OF CHAR;
  92.                             wdwTitle  : ARRAY [0..139] OF CHAR;
  93.                             VslSize,
  94.                             VslPos,
  95.                             HslSize,
  96.                             HslPos    : INTEGER;        (* Die Positionen und Gr”žen der Slider *)
  97.                             onlyTop   : BOOLEAN;        (* Nur dieses Fenster darf Topwindow sein *)
  98.                             lastOnlyTop: INTEGER;       (* Fensternummer des letzten Windows, welches nur Top sein durfte *)
  99.                             wdwMenu   : ADDRESS;        (* Adresse eines Menus im Fenster *)
  100.                             wdwDial   : ADDRESS;        (* Adresse eines Dials im Fenster *)
  101.                             
  102.                             (* Prozeduren *)
  103.                             hdlButton : handleButtonProc;
  104.                             hdlKey    : handleKeyProc;
  105.                             hdlTimer  : handleTimerProc;
  106.  
  107.                             hdlRect   : handleRectProc;
  108.  
  109.                             hdlSnap   : snapProc; 
  110.                             hdlClose  : closeProc;
  111.                             hdlDraw   : drawProc; 
  112.                             hdlTop    : topProc;   (* Wird aufgerufen, wenn das Fenster getoppt 
  113.                                                       * werden soll. Kann auch False zurckgeben 
  114.                                                       *)
  115.                             hdlUntop  : untopProc; 
  116.                             hdlUpdate : updateProc;  (* Wird aufgerufen vor 
  117.                                                       * geplanten Bildschirmausgaben *)
  118.                             setNewWdw     : setWorkProc;     
  119.                             wdwGetScroll  : getRectProc;
  120.                                             (* wird aufgerufen, wenn der Arbeits-
  121.                                              * ausschnitt des Fensters sich 
  122.                                              * ver„ndert hat.
  123.                                              *)
  124.                             hdlHide   : hideProc;
  125.                                         (* wird aufgerufen, wenn das Fenster iconifiziert
  126.                                          * oder versteckt wird bzw. beim Wiederherstellen
  127.                                          *)
  128.  
  129.                             (* Drag & Drop Support *)
  130.                             ddClientInstalled : BOOLEAN;
  131.                             ddGetExts   : getExtsProc;
  132.                             ddAcceptData: acceptDataProc;
  133.                             ddWriteData : writeDataProc;
  134.                             ddServerInstalled: BOOLEAN;
  135.                             ddReadData  : readDataProc;
  136.                             ddGetHeader : getHeaderProc;
  137.  
  138.                             special   : ADDRESS;     (* Variabler Parameter *)
  139.                             next,
  140.                             prev      : ptrWdwSlot;
  141.                           END;
  142.  
  143. (* globale Variablen in diesem Modul *)
  144. VAR windows :       ptrWdwSlot;
  145.     control7:       POINTER TO ADDRESS; (* it's tricky... *)
  146.     control9:       POINTER TO ADDRESS;
  147.     multiTOS:       BOOLEAN;
  148.     magIx:          BOOLEAN;
  149.     magIxVer:       CARDINAL;
  150.     onlyOneTop:     INTEGER;
  151.     iconHdl:        ADDRESS;
  152.     allIconified:   BOOLEAN;
  153.     iconifySupportEnabled: BOOLEAN;
  154.     isInRectList:   BOOLEAN;        (* Gerade in WF_FIRST, WF_NEXT *)
  155.     globalMenu  : ADDRESS;
  156.     menuLength  : INTEGER;
  157.     menuDisabled: BOOLEAN;
  158.     MagicPCKeyTrans: BOOLEAN;
  159.     disableCounter: INTEGER;
  160.     handleGlobalKey: handleGlobalKeyProc;
  161.     handleGlobalMess: handleMessProc;
  162.  
  163.  
  164. (*====================================================*
  165.  *                                                    *
  166.  *   Forward-Funktionen                               *
  167.  *                                                    *
  168.  *====================================================*)
  169.  
  170. PROCEDURE SendClosed (wdw : INTEGER; apId : INTEGER); FORWARD;
  171. PROCEDURE SendFulled (wdw : INTEGER; apId : INTEGER); FORWARD;
  172. PROCEDURE SendTop    (wdw : INTEGER; apId : INTEGER); FORWARD;
  173.  
  174. (*====================================================*
  175.  *                                                    *
  176.  *   Low-Level-Funktionen                             *
  177.  *                                                    *
  178.  *====================================================*)
  179.  
  180. (* Rechteck- und Clipfunctionen *)
  181.  
  182. PROCEDURE SetClip (hdl : INTEGER; clip : ARRAY OF LOC; relative : BOOLEAN);
  183.   VAR cl : POINTER TO Rectangle;
  184. BEGIN
  185.   cl := ADR (clip);
  186.   IF relative
  187.   THEN
  188.     WITH cl^ DO
  189.       INC (w, x); DEC (w);
  190.       INC (h, y); DEC (h);
  191.     END;
  192.   END;
  193.   IF hdl > 0 THEN MagicVDI.SetClipping (hdl, cl^, TRUE); END;
  194. END SetClip;
  195.  
  196. PROCEDURE ClipWork (wdwPtr : ptrWdwSlot);
  197.   VAR clip : Rectangle;
  198. BEGIN
  199.   clip := RectFuncs.ClipRect (deskSize, wdwPtr^.wdwWork);
  200.   SetClip (wdwPtr^.vdi, clip, TRUE);
  201. END ClipWork;
  202.  
  203. PROCEDURE RectList (wdw: INTEGER; flag: INTEGER; 
  204.                     VAR work: Rectangle): BOOLEAN;
  205. (* Gibt TRUE und ein Rechteck zurck, solange noch 
  206.  * ein Rechteck in der Rechteckliste ist
  207.  *)
  208. VAR b: BOOLEAN;
  209. BEGIN
  210.  b:= FALSE;
  211.  IF wdw > 0 THEN
  212.   MagicAES.WindGet (wdw, flag + 11, work);
  213.   b:= NOT ((work.w = 0) OR (work.h = 0));
  214.  END;
  215.  isInRectList := b;
  216.  RETURN b;
  217. END RectList;
  218.  
  219. PROCEDURE RectListActive (): BOOLEAN; 
  220. BEGIN
  221.   RETURN isInRectList;
  222. END RectListActive;
  223.  
  224.     (* Default-Prozeduren *)
  225.  
  226. PROCEDURE defDraw (wdw, vdi: INTEGER; special: ADDRESS; clip: Rectangle);
  227. BEGIN
  228.   IF vdi > 0
  229.   THEN
  230.     mtUtils.AbsRect (clip);
  231.     v.int := MagicVDI.SetFillcolor (vdi, 0);   (* weiž *)
  232.     v.int := MagicVDI.SetFillinterior (vdi, 1); (* solide *)
  233.     MagicVDI.FillRectangle(vdi, clip);
  234.   END;
  235. END defDraw;
  236.  
  237. PROCEDURE defButton (wdw, vdi: INTEGER; special: ADDRESS; mx, my : INTEGER;
  238.                      kstate, buttons : BITSET; clicks: INTEGER): BOOLEAN;
  239. BEGIN
  240.   RETURN FALSE
  241. END defButton;
  242.  
  243. PROCEDURE defKey (wdw, vdi: INTEGER; special: ADDRESS; taste: INTEGER; key, scan: CHAR; kstate: BITSET): BOOLEAN;
  244. BEGIN
  245.   RETURN FALSE
  246. END defKey;
  247.  
  248. PROCEDURE defTimer (wdw, vdi: INTEGER; special: ADDRESS): BOOLEAN;
  249. BEGIN
  250.   RETURN FALSE
  251. END defTimer;
  252.  
  253. PROCEDURE defRect (wdw, vdi: INTEGER; special: ADDRESS; which: INTEGER): BOOLEAN;
  254. BEGIN
  255.   RETURN FALSE
  256. END defRect;
  257.  
  258. PROCEDURE defSnap (wdw, vdi: INTEGER; special: ADDRESS; VAR r: Rectangle);
  259. END defSnap;
  260.  
  261. PROCEDURE defClose (wdw, vdi: INTEGER; special: ADDRESS; force: BOOLEAN): BOOLEAN;
  262. BEGIN
  263.   RETURN TRUE
  264. END defClose;
  265.  
  266. PROCEDURE defTop (wdw, vdi: INTEGER; special: ADDRESS): BOOLEAN;
  267. BEGIN
  268.   RETURN TRUE
  269. END defTop;
  270.  
  271. PROCEDURE defUntop (wdw, vdi: INTEGER; special: ADDRESS);
  272. END defUntop;
  273.  
  274. PROCEDURE defUpdate (wdw, vdi: INTEGER; special: ADDRESS; begin: BOOLEAN);
  275. BEGIN
  276.   IF begin
  277.   THEN
  278.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  279.     mtAppl.MouseOff();
  280.   ELSE
  281.     mtAppl.MouseOn();
  282.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  283.   END;
  284. END defUpdate;
  285.  
  286. PROCEDURE defSetwork (wdw, vdi: INTEGER; special: ADDRESS; doc: LongRect; slided: BOOLEAN);
  287. END defSetwork;
  288.  
  289. PROCEDURE defGetrect (wdw, vdi: INTEGER; special: ADDRESS; VAR work: Rectangle);
  290. END defGetrect;
  291.  
  292. PROCEDURE defHide (wdw, vdi: INTEGER; special: ADDRESS; hide: BOOLEAN);
  293. END defHide;
  294.  
  295.     (* Window neu zeichnen *)
  296. PROCEDURE AdaptIconPos (work : Rectangle);
  297.   VAR ob : POINTER TO MagicAES.OBJECT;
  298.       rp : POINTER TO Rectangle;
  299. BEGIN
  300.   IF iconHdl # NIL
  301.   THEN
  302.     ob := iconHdl;
  303.     rp := ADR(ob^.obX);
  304.     rp^ := work;
  305.     (*
  306.     WITH ob^ DO
  307.       obX := work.x;
  308.       obY := work.y;
  309.       obWidth := work.w;
  310.       obHeight := work.h;
  311.     END;
  312.     *)
  313.   END;
  314. END AdaptIconPos;
  315.  
  316. PROCEDURE updateWdw (wdwPtr : ptrWdwSlot; frame : Rectangle);
  317. (* In dieser Prozedur wird die Rechteckliste abgeklappert und
  318.  * fr alle Rechtecke, die vorhanden sind,
  319.  * die Zeichenprozedur fr das Fenster aufgerufen. 
  320.  * Clipping wird schon gesetzt.
  321.  *)
  322.   VAR work : Rectangle;
  323.       c : Rectangle;
  324. BEGIN
  325.   WITH wdwPtr^ DO 
  326.     IF isIcon
  327.     THEN
  328.       MagicAES.WindGet (wdw, MagicAES.WFWORKXYWH, wdwWork);
  329.       AdaptIconPos (wdwWork);
  330.       IF RectList (wdw, 0, work)
  331.       THEN
  332.         MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  333.         MagicAES.GrafMouse (MagicAES.MOFF, NIL);
  334.         REPEAT
  335.           (* kleinsten Redrawbereich bestimmen *)
  336.           c := RectFuncs.ClipRect (work, deskSize);
  337.           c := RectFuncs.ClipRect (frame, c);
  338.           IF (c.w > 0) & (c.h > 0) THEN
  339.             SetClip (vdi, c, TRUE);
  340.             IF iconHdl # NIL
  341.             THEN
  342.               MagicAES.ObjcDraw (iconHdl, 0, 8, c);
  343.             ELSIF vdi > 0 
  344.             THEN
  345.               (* Nur l”schen mit aktuellen Attributen und Farbe! *)
  346.               (* v.int := MagicVDI.SetFillcolor (vdi, 0); *)
  347.               c.w := c.x + c.w - 1;
  348.               c.h := c.y + c.h - 1;
  349.               MagicVDI.FillRectangle(vdi, c);
  350.             END;
  351.           END;
  352.         UNTIL ~RectList (wdw, 1, work);
  353.         MagicAES.GrafMouse (MagicAES.MON, NIL);
  354.         MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  355.       END;
  356.     ELSE
  357.       hdlUpdate (wdw, vdi, special, TRUE);
  358.       IF RectList (wdw, 0, work)
  359.       THEN
  360.         REPEAT
  361.           (* kleinsten Redrawbereich bestimmen *)
  362.           c := RectFuncs.ClipRect (work, deskSize);
  363.           c := RectFuncs.ClipRect (frame, c);
  364.           IF (c.w > 0) & (c.h > 0) THEN
  365.             SetClip (vdi, c, TRUE);
  366.             hdlDraw (wdw, vdi, special, c);
  367.           END;
  368.         UNTIL ~RectList (wdw, 1, work);
  369.       END;
  370.       hdlUpdate (wdw, vdi, special, FALSE);
  371.     END;
  372.   END;
  373. END updateWdw;
  374.  
  375.         (* Scroll-Funktionen *)
  376.  
  377. PROCEDURE rawScroll (wdwPtr: ptrWdwSlot; dir: INTEGER; 
  378.                      VAR area : Rectangle; 
  379.                      height: INTEGER; amount: INTEGER);
  380. (* Fr eine schnellere Ausfhrung der Blit-Operationen 
  381.  * werden hier die VDI-Arrays direkt gefllt und direkt
  382.  * der entsprechende Call ausgefhrt, ohne ber die
  383.  * Library zu gehen.
  384.  *)
  385.   VAR screen     : MagicVDI.MFDB;
  386. BEGIN
  387.   (* build screen MFDB *)
  388.   screen.fdWdwidth:= (mtAppl.MaxWidth + 15) DIV 16;
  389.   screen.fdW:=       screen.fdWdwidth * 16;
  390.   screen.fdH:=       mtAppl.MaxHeight;
  391.   screen.fdStand:=   0;
  392.   screen.fdNplanes:= mtAppl.Bitplanes;
  393.   screen.fdAddr:=    NIL;
  394.  
  395.   (* erst kopieren *)
  396.   VDIIntIn[0]:= 3;  (* E = Q *)
  397.   control7^:= ADR (screen);
  398.   control9^:= ADR (screen);
  399.   IF dir = UP
  400.   THEN
  401.     (* scrollUp *)
  402.     WITH area DO
  403.       VDIPtsIn[0]:= x;
  404.       VDIPtsIn[1]:= y;
  405.       VDIPtsIn[2]:= x + w - 1;
  406.       VDIPtsIn[3]:= y + height - 1;
  407.       VDIPtsIn[4]:= x;
  408.       VDIPtsIn[5]:= y + amount;
  409.       VDIPtsIn[6]:= x + w - 1;
  410.       VDIPtsIn[7]:= y + height + amount - 1;
  411.     END;
  412.     WITH wdwPtr^ DO
  413.       MagicVDI.VDICall (109, 4, 1, 0, vdi);
  414.       (* jetzt RectFuncs.ClipRect berechnen und neu zeichnen *)
  415.       IF area.x - 2 <= wdwPtr^.wdwWork.x
  416.       THEN
  417.         INC (area.x, pixOff);
  418.         DEC (area.w, pixOff);
  419.       END;
  420.       SetClip (vdi, Rectangle{area.x, area.y, area.w, amount}, TRUE);
  421.       hdlDraw (wdw, vdi, special, Rectangle{area.x, area.y, area.w, amount});
  422.     END;
  423.   ELSE
  424.     (* scroll down *)
  425.     WITH area DO
  426.       VDIPtsIn[0]:= x;
  427.       VDIPtsIn[1]:= y + amount ;
  428.       VDIPtsIn[2]:= x + w - 1;
  429.       VDIPtsIn[3]:= y + height + amount - 1;
  430.       VDIPtsIn[4]:= x;
  431.       VDIPtsIn[5]:= y ;
  432.       VDIPtsIn[6]:= x + w - 1;
  433.       VDIPtsIn[7]:= y + height - 1;
  434.     END;
  435.     WITH wdwPtr^ DO
  436.       MagicVDI.VDICall (109, 4, 1, 0, vdi);
  437.       IF area.x - 2 <= wdwPtr^.wdwWork.x
  438.       THEN
  439.         INC (area.x, pixOff);
  440.         DEC (area.w, pixOff);
  441.       END;
  442.       (* jetzt RectFuncs.ClipRect berechnen und neu zeichnen *)
  443.       SetClip (vdi, Rectangle{area.x, area.y+height, area.w, amount}, TRUE);
  444.       hdlDraw (wdw, vdi, special, Rectangle{area.x, area.y+height, area.w, amount});
  445.     END;
  446.   END;
  447. END rawScroll;
  448.  
  449. PROCEDURE FindWindow (wdw : INTEGER) : ptrWdwSlot; FORWARD;
  450.  
  451. PROCEDURE ScrollInWdw (wdw: INTEGER; VAR source: Rectangle; 
  452.                        dir: INTEGER; amount: INTEGER);
  453.   VAR wdwPtr: ptrWdwSlot;
  454.       copyLines  : INTEGER;
  455.       work, c    : Rectangle;
  456. BEGIN
  457.   wdwPtr := FindWindow (wdw);
  458.   IF wdwPtr # NIL
  459.   THEN
  460.    WITH wdwPtr^ DO
  461.     source := RectFuncs.ClipRect (wdwWork, source);
  462.     (* Rechteckliste abfragen *)
  463.     IF RectList (wdw, 0, work)
  464.     THEN
  465.       hdlUpdate (wdw, vdi, special, TRUE);
  466.       REPEAT
  467.         ClipWork (wdwPtr);
  468.         (* kleinsten Redrawbereich bestimmen *)
  469.         c := RectFuncs.ClipRect (work, deskSize);
  470.         c := RectFuncs.ClipRect (c, source);
  471.         copyLines := c.h-amount;
  472.         IF (c.w > 0) & (copyLines > 0) THEN
  473.           rawScroll (wdwPtr, dir, c, copyLines, amount);
  474.         ELSIF c.w > 0
  475.         THEN
  476.           SetClip (vdi, c, TRUE);
  477.           hdlDraw (wdw, vdi, special, c);
  478.         END;
  479.         ClipWork (wdwPtr);
  480.       UNTIL ~RectList (wdw, 1, work);
  481.       hdlUpdate (wdw, vdi, special, FALSE);
  482.     END;
  483.     (*
  484.     rawScroll (wdwPtr, dir, source, source.h, amount);
  485.     *)
  486.    END;
  487.   END;
  488. END ScrollInWdw;
  489.  
  490. PROCEDURE scrollWdw (wdwPtr : ptrWdwSlot; dir : INTEGER; lines : LONGINT);
  491. (* lines ist der Betrag in Pixelzeilen, um den gescrollt werden soll.
  492.  *)
  493.   VAR 
  494.       pixLines   : INTEGER;
  495.       copyLines  : INTEGER;
  496.       work, c    : Rectangle;
  497.  
  498. VAR x, y, w, h : INTEGER;
  499.  
  500. BEGIN
  501.   WITH wdwPtr^ DO 
  502.     IF isIcon OR isHidden THEN RETURN END;
  503.     (* calc scroll Area *)
  504.     (* calc pixel lines *)
  505.     IF (lines <= LONG(wdwWork.h))
  506.     THEN
  507.       pixLines := SHORT(lines);
  508.       copyLines := (wdwWork.h - SHORT(lines));
  509.     END;
  510.     IF (lines < LONG(wdwWork.h)) 
  511.     THEN
  512.       (* Rechteckliste abfragen *)
  513.       IF RectList (wdw, 0, work)
  514.       THEN
  515.         hdlUpdate (wdw, vdi, special, TRUE);
  516.         REPEAT
  517.           ClipWork (wdwPtr);
  518.           (* kleinsten Redrawbereich bestimmen *)
  519.           c := RectFuncs.ClipRect (work, deskSize);
  520.           c := RectFuncs.ClipRect (c, wdwWork);
  521.           copyLines := c.h-SHORT(lines);
  522.           IF (c.w > 0) & (copyLines > 0) THEN
  523.             rawScroll (wdwPtr, dir, c, copyLines, pixLines);
  524.           ELSIF c.w > 0
  525.           THEN
  526.             SetClip (vdi, c, TRUE);
  527.             hdlDraw (wdw, vdi, special, c);
  528.           END;
  529.           ClipWork (wdwPtr);
  530.         UNTIL ~RectList (wdw, 1, work);
  531.         hdlUpdate (wdw, vdi, special, FALSE);
  532.       END;
  533.     ELSE
  534.       (* komplett neuzeichnen *)
  535.       updateWdw (wdwPtr, wdwWork);
  536.     END;
  537.   END (* WITH wdwPtr^ DO *);
  538. END scrollWdw;
  539.  
  540. PROCEDURE scrollLR (wdwPtr : ptrWdwSlot; dir : INTEGER; amount : INTEGER);
  541. VAR copy     : MagicVDI.tBigPxyArray;
  542.     fill     : MagicVDI.tPxyArray;
  543.     work,
  544.     c,
  545.     clip     : Rectangle;
  546.     pscrMFDB,
  547.     pdesMFDB : MagicVDI.MFDB;
  548. BEGIN
  549.   pscrMFDB.fdAddr := NIL;
  550.   pdesMFDB.fdAddr := NIL;
  551.   WITH wdwPtr^ DO
  552.     IF isIcon OR isHidden THEN RETURN END;
  553.     IF amount < wdwWork.w
  554.     THEN
  555.       (* Rechteckliste abfragen *)
  556.       IF RectList (wdw, 0, work)
  557.       THEN
  558.         hdlUpdate (wdw, vdi, special, TRUE);
  559.         REPEAT
  560.           (* kleinsten Redrawbereich bestimmen *)
  561.           c := RectFuncs.ClipRect (work, deskSize);
  562.           c := RectFuncs.ClipRect (c, wdwWork);
  563.           IF (c.w > 0) THEN
  564.             ClipWork (wdwPtr);
  565.             IF c.w > amount 
  566.             THEN
  567.               IF dir = LEFT THEN
  568.                 WITH c DO 
  569.                   copy[0] := x;
  570.                   copy[1] := y;
  571.                   copy[2] := BinOps.HigherInt(x, x+w-1-amount);   
  572.                   copy[3] := y+h-1;
  573.                   copy[4] := x+amount;
  574.                   copy[5] := y;
  575.                   copy[6] := x+w-1;
  576.                   copy[7] := y+h-1;
  577.                 END;
  578.               ELSE
  579.                 WITH c DO 
  580.                   copy[0] := x+amount;
  581.                   copy[1] := y;
  582.                   copy[2] := x+w-1;
  583.                   copy[3] := y+h-1;
  584.                   copy[4] := x;
  585.                   copy[5] := y;
  586.                   copy[6] := BinOps.HigherInt (x, x+w-1-amount);   
  587.                   copy[7] := y+h-1;
  588.                 END;
  589.               END;
  590.               MagicVDI.CopyRasterOpaque(vdi, 3, copy, pscrMFDB, pdesMFDB);
  591.             END;
  592.             clip := c;
  593.             
  594.             (* Redrawbereich berechnen *)
  595.             WITH c DO
  596.               clip.y := y;
  597.               clip.h := h;
  598.               IF dir = LEFT
  599.               THEN
  600.                 clip.x := x;
  601.                 clip.w := BinOps.LowerInt (amount + pixOff, w);
  602.               ELSE
  603.                 clip.x := BinOps.HigherInt (x, x+w-1-amount);
  604.                 clip.w := c.x + c.w - clip.x;
  605.               END;
  606.             END;
  607.             (*
  608.             IF dir = LEFT THEN
  609.               WITH c DO 
  610.                 fill[0] := x;                 fill[1] := y;
  611.                 fill[2] := x+amount+pixOff-1; fill[3] := y+h-1;
  612.               END;
  613.               IF fill[2] > c.x+c.w-1 
  614.               THEN fill[2] := c.x+c.w-1  
  615.               END;
  616.             ELSE
  617.               WITH c DO 
  618.                 fill[0] := BinOps.HigherInt (x, x+w-1-amount); 
  619.                 fill[1] := y;
  620.                 fill[2] := x+w-1;        
  621.                 fill[3] := y+h-1;
  622.               END;
  623.             END;
  624.             MagicVDI.FillRectangle(vdi, fill);
  625.             IF (fill[0]-2 <= wdwWork.x) THEN 
  626.               INC (fill[0], pixOff); 
  627.               IF fill[0] > c.x+c.w-1 
  628.               THEN fill[0] := c.x+c.w-1  
  629.               END;
  630.             END;
  631.             
  632.             clip.x := fill[0];
  633.             clip.y := fill[1];
  634.             clip.w := fill[2]-fill[0]+1;
  635.             clip.h := fill[3]-fill[1]+1;
  636.             *)
  637.             SetClip (vdi, clip, TRUE);
  638.             hdlDraw (wdw, vdi, special, clip);
  639.  
  640.             (* Linken Rand l”schen *)
  641.             IF (c.x-pixOff <= wdwWork.x)
  642.             THEN
  643.               (* pixOff ausfllen *)
  644.               IF pixOff > 0
  645.               THEN
  646.                 WITH c DO 
  647.                   fill[0] := wdwWork.x;             fill[1] := y;
  648.                   fill[2] := wdwWork.x+pixOff-1;    fill[3] := y+h-1;
  649.                 END;
  650.                 ClipWork (wdwPtr);
  651.                 MagicVDI.FillRectangle(vdi, fill);
  652.               END;
  653.             END;
  654.           END;
  655.         UNTIL ~RectList (wdw, 1, work);
  656.         hdlUpdate (wdw, vdi, special, FALSE);
  657.       END;
  658.       ClipWork (wdwPtr);
  659.     ELSE
  660.       updateWdw (wdwPtr, wdwWork);
  661.     END;
  662.   END;
  663. END scrollLR;
  664.  
  665. (*====================================================*
  666.  *                                                    *
  667.  *   High-Level-Funktionen                            *
  668.  *                                                    *
  669.  *====================================================*)
  670.  
  671.          (* Sliderberechnungen *)
  672.  
  673. PROCEDURE CalcVSlider (wdwPtr : ptrWdwSlot);
  674.   VAR r       : REAL;
  675.       a, b    : LONGINT;
  676.       vslSize : INTEGER;
  677.       vslPos  : INTEGER;
  678.       vslLong : LONGINT;
  679. BEGIN
  680.   WITH wdwPtr^ DO
  681.     IF ~(MagicAES.VSLIDE IN comps) OR isIcon OR isHidden THEN RETURN END;
  682.     (* Gr”že berechnen *)
  683.     a := (document.h+1) * yFactor;
  684.     b := LONG(wdwWork.h);
  685.     IF a > 0 THEN
  686.       r := 1000.0 * (FLOAT (b)/FLOAT(a));
  687.       IF (r > 1000.0) OR (r < 0.0) THEN r := 1000.0 END;
  688.     ELSE
  689.       r := 1000.0;
  690.     END;
  691.     vslSize := VAL (INTEGER, TRUNC(r));
  692.     (* Position berechnen *)
  693.     IF document.y = 0
  694.     THEN
  695.       vslPos := 0
  696.     ELSE       a := document.y * yFactor;
  697.       b := ((document.h+1) * yFactor) - LONG(wdwWork.h);
  698.       IF b > 0 THEN
  699.         vslLong := VAL (LONGINT,1000.0 * (FLOAT (a) / FLOAT (b)));
  700.         IF (vslLong > 1000) OR (vslLong < 0) THEN vslPos := 1000 
  701.         ELSE
  702.           vslPos := VAL (INTEGER, SHORT( vslLong));
  703.         END;
  704.       ELSE
  705.         vslPos := 1000;
  706.       END;
  707.     END;
  708.     IF vslSize # VslSize THEN 
  709.       MagicAES.WindSet (wdw, MagicAES.WFVSLSIZE, Rectangle {vslSize, 0,0,0});
  710.       VslSize := vslSize;
  711.     END;
  712.     IF vslPos # VslPos THEN 
  713.       MagicAES.WindSet (wdw, MagicAES.WFVSLIDE, Rectangle {vslPos, 0,0,0});
  714.       VslPos := vslPos;
  715.     END;
  716.   END;
  717. END CalcVSlider;
  718.  
  719. PROCEDURE CalcHSlider (wdwPtr : ptrWdwSlot);
  720.   VAR r       : REAL;
  721.       a, b    : LONGINT;
  722.       hslSize : INTEGER;
  723.       hslPos  : INTEGER;
  724.       hslLong : LONGINT;
  725. BEGIN
  726.   WITH wdwPtr^ DO
  727.     IF ~(MagicAES.HSLIDE IN comps) OR isIcon OR isHidden THEN RETURN END;
  728.     (* Gr”že berechnen *)
  729.     a := (document.w+1) * xFactor; 
  730.     b := LONG(wdwWork.w);
  731.     IF a > 0
  732.     THEN
  733.       r := 1000.0 * (FLOAT (b)/FLOAT(a));
  734.       IF (r > 1000.0) OR (r < 0.0) THEN r := 1000.0 END;
  735.     ELSE
  736.       r := 1000.0;
  737.     END;
  738.     hslSize := VAL (INTEGER, TRUNC(r));
  739.     (* Position berechnen *)
  740.     IF document.x = 0
  741.     THEN
  742.       hslPos := 0
  743.     ELSE
  744.       a := document.x * xFactor;
  745.       b := ((document.w+1) * xFactor) - LONG(wdwWork.w);
  746.       IF b > 0 THEN
  747.         hslLong := VAL (LONGINT,1000.0 * (FLOAT (a) / FLOAT (b)));
  748.         IF (hslLong > 1000) OR (hslLong < 0) THEN 
  749.           hslPos := 1000 
  750.         ELSE
  751.           hslPos := VAL (INTEGER, SHORT( hslLong ) );
  752.         END;
  753.       ELSE
  754.         hslPos := 1000;
  755.       END;
  756.     END;
  757.     IF hslSize # HslSize THEN 
  758.       MagicAES.WindSet (wdw, MagicAES.WFHSLSIZE, Rectangle {hslSize, 0,0,0});
  759.       HslSize := hslSize;
  760.     END;
  761.     IF hslPos # HslPos THEN 
  762.       MagicAES.WindSet (wdw, MagicAES.WFHSLIDE, Rectangle {hslPos, 0,0,0});
  763.       HslPos := hslPos;
  764.     END;
  765.   END;
  766. END CalcHSlider;
  767.  
  768.      (* High-Level Scroll-Funktionen *)
  769.  
  770. PROCEDURE scrollUp (wdwPtr : ptrWdwSlot; lines : INTEGER);
  771.   VAR oldStart : LONGINT;
  772. BEGIN
  773.   WITH wdwPtr^ DO
  774.     IF document.y > 0 THEN
  775.       oldStart := document.y;
  776.       DEC (document.y, LONG(lines) * minScrollH);
  777.       document.y := BinOps.HigherLInt (0, document.y);
  778.       setNewWdw (wdw, vdi, special, document, TRUE);
  779.       scrollWdw (wdwPtr, UP, SHORT((oldStart - document.y)*yFactor));
  780.       CalcVSlider (wdwPtr);
  781.     END;
  782.   END;
  783. END scrollUp;
  784.  
  785. PROCEDURE scrollDown (wdwPtr : ptrWdwSlot; lines : INTEGER);
  786.   VAR oldStart : LONGINT;
  787. BEGIN
  788.   WITH wdwPtr^ DO
  789.     IF document.y + pageH < document.h THEN
  790.       oldStart := document.y;
  791.       INC (document.y, LONG(lines) * minScrollH);
  792.       document.y := BinOps.LowerLInt (document.y, document.h - pageH);
  793.       setNewWdw (wdw, vdi, special, document, TRUE);
  794.       scrollWdw (wdwPtr, DOWN, SHORT((document.y - oldStart)*yFactor));
  795.       CalcVSlider (wdwPtr);
  796.     END;
  797.   END;
  798. END scrollDown;
  799.  
  800. PROCEDURE scrollLeft (wdwPtr : ptrWdwSlot; cols : INTEGER);
  801.   VAR oldStart : LONGINT;
  802. BEGIN
  803.   WITH wdwPtr^ DO
  804.     IF document.x > 0 
  805.     THEN
  806.       oldStart := document.x;
  807.       DEC (document.x, LONG(cols) * minScrollW);
  808.       document.x := BinOps.HigherLInt (0, document.x);
  809.       setNewWdw (wdw, vdi, special, document, TRUE);
  810.       scrollLR (wdwPtr, LEFT, SHORT(xFactor*(oldStart-document.x)));
  811.       CalcHSlider (wdwPtr);
  812.     END;
  813.   END;
  814. END scrollLeft;
  815.  
  816. PROCEDURE scrollRight (wdwPtr : ptrWdwSlot; cols : INTEGER);
  817.   VAR oldStart : LONGINT;
  818. BEGIN
  819.   WITH wdwPtr^ DO
  820.     IF document.x + pageW < document.w - 1 THEN
  821.       oldStart := document.x;
  822.       INC (document.x, LONG(cols) * minScrollW);
  823.       document.x := BinOps.LowerLInt (document.w - pageW, document.x);
  824.       setNewWdw (wdw, vdi, special, document, TRUE);
  825.       scrollLR (wdwPtr, RIGHT, SHORT(xFactor*(document.x - oldStart)));
  826.       CalcHSlider (wdwPtr);
  827.     END;
  828.   END;
  829. END scrollRight;
  830.  
  831. PROCEDURE pageUp (wdwPtr : ptrWdwSlot; pages : INTEGER);
  832.   VAR oldStart : LONGINT;
  833. BEGIN
  834.   WITH wdwPtr^ DO
  835.     IF document.y > 0 THEN
  836.       oldStart := document.y;
  837.       DEC (document.y, pageH*LONG(pages));
  838.       document.y := BinOps.HigherLInt (0, document.y);
  839.       setNewWdw (wdw, vdi, special, document, TRUE);
  840.       scrollWdw (wdwPtr, UP, SHORT((oldStart - document.y)*yFactor));
  841.       CalcVSlider (wdwPtr);
  842.     END;
  843.   END;
  844. END pageUp;
  845.  
  846. PROCEDURE pageDown (wdwPtr : ptrWdwSlot; pages : INTEGER);
  847.   VAR oldStart : LONGINT;
  848. BEGIN
  849.   WITH wdwPtr^ DO
  850.     IF document.y + pageH < document.h THEN
  851.       oldStart := document.y;
  852.       INC (document.y, pageH*LONG(pages));
  853.       document.y := BinOps.LowerLInt(document.y , document.h-pageH);
  854.       setNewWdw (wdw, vdi, special, document, TRUE);
  855.       scrollWdw (wdwPtr, DOWN, SHORT((document.y - oldStart)*yFactor));
  856.       CalcVSlider (wdwPtr);
  857.     END;
  858.   END;
  859. END pageDown;
  860.  
  861. PROCEDURE pageLeft (wdwPtr : ptrWdwSlot; pages : INTEGER);
  862.   VAR oldStart : LONGINT;
  863. BEGIN
  864.   WITH wdwPtr^ DO
  865.     IF document.x > 0 THEN
  866.       oldStart := document.x;
  867.       DEC (document.x, pageW*LONG(pages));
  868.       document.x := BinOps.HigherLInt (0, document.x);
  869.       setNewWdw (wdw, vdi, special, document, TRUE);
  870.       scrollLR (wdwPtr, LEFT, SHORT(xFactor* (oldStart-document.x)));
  871.       CalcHSlider (wdwPtr);
  872.     END;
  873.   END;
  874. END pageLeft;
  875.  
  876. PROCEDURE pageRight (wdwPtr : ptrWdwSlot; pages : INTEGER);
  877.   VAR oldStart : LONGINT;
  878. BEGIN
  879.   WITH wdwPtr^ DO
  880.     IF document.x + pageW < document.w - 1 THEN
  881.       oldStart := document.x;
  882.       INC (document.x, pageW*LONG(pages));
  883.       document.x := BinOps.LowerLInt (document.x, document.w - pageW);
  884.       setNewWdw (wdw, vdi, special, document, TRUE);
  885.       scrollLR (wdwPtr, RIGHT, SHORT(xFactor*(document.x - oldStart)));
  886.       CalcHSlider (wdwPtr);
  887.     END;
  888.   END;
  889. END pageRight;
  890.  
  891. PROCEDURE FindWindow (wdw : INTEGER) : ptrWdwSlot;
  892.   VAR wdwPtr : ptrWdwSlot;
  893. BEGIN
  894.   wdwPtr := windows;
  895.   WHILE (wdwPtr # NIL) & (wdwPtr^.wdw # wdw) DO wdwPtr := wdwPtr^.next END;
  896.   RETURN wdwPtr;
  897. END FindWindow;
  898.  
  899. PROCEDURE FindTop () : ptrWdwSlot;
  900.   VAR wdw , vdi : INTEGER;
  901. BEGIN
  902.   GetTopWindow (wdw, vdi);
  903.   RETURN FindWindow (wdw);
  904. END FindTop;
  905.  
  906. (*====================================================*
  907.  *                                                    *
  908.  *   Event-Handling-Funktionen                        *
  909.  *                                                    *
  910.  *====================================================*)
  911. PROCEDURE untopWdw (wdwPtr : ptrWdwSlot);
  912. BEGIN
  913.   WITH wdwPtr^ DO
  914.     IF ~isTop THEN RETURN END;
  915.     isTop := FALSE;
  916.     IF hdlUntop # untopProc(NIL) THEN
  917.       hdlUntop (wdw, vdi, special);
  918.     END;
  919.   END;
  920. END untopWdw;
  921.  
  922. PROCEDURE topWdw (wdwPtr : ptrWdwSlot; doTop : BOOLEAN);
  923.   VAR r : Rectangle;
  924.       oldTopPtr : ptrWdwSlot;
  925. BEGIN
  926.  (* altes Top-Window feststellen *)
  927.   IF (onlyOneTop >= 0) & (wdwPtr^.wdw # onlyOneTop) THEN 
  928.     (* onlyOneTopWdw toppen *)
  929.     wdwPtr := FindWindow (onlyOneTop);
  930.     IF wdwPtr # NIL
  931.     THEN
  932.       topWdw (wdwPtr, doTop);
  933.     END;
  934.     RETURN 
  935.   END;
  936.   WITH wdwPtr^ DO
  937.     oldTopPtr := FindTop ();
  938.     IF (oldTopPtr # NIL) & doTop & (oldTopPtr^.wdw # wdw) THEN
  939.       (* Altes Topwindow untoppen *)
  940.       untopWdw (oldTopPtr);
  941.     END;
  942.     IF hdlTop (wdw, vdi, special)
  943.     THEN
  944.       IF doTop THEN
  945.         MagicAES.WindSet (wdw, MagicAES.WFTOP, r);
  946.       END;
  947.       theTopWindow := wdw;
  948.       NewWindowIsTop (wdw, mtAppl.ApplIdent);
  949.       isTop := TRUE;
  950.     END;
  951.   END;
  952. END topWdw;
  953.  
  954. PROCEDURE BottomOfQueue(VAR item, apid: INTEGER); FORWARD;
  955. PROCEDURE TopLastWindow(); FORWARD;
  956. PROCEDURE BringToBottom (wdw, apId : INTEGER); FORWARD;
  957.  
  958. PROCEDURE backdropWdw (wdwPtr : ptrWdwSlot);
  959.   VAR r : Rectangle;
  960. BEGIN
  961.   WITH wdwPtr^ DO
  962.     IF (onlyOneTop >= 0) & (wdw = onlyOneTop) 
  963.     THEN
  964.       (* Alle nach hinten schicken *)
  965.     ELSE
  966.       untopWdw (wdwPtr);
  967.       MagicAES.WindSet (wdw, MagicAES.WFMBACKDROP, r);
  968.       BringToBottom (wdw, mtAppl.ApplIdent);
  969.     END;
  970.   END;
  971. END backdropWdw;
  972.  
  973. PROCEDURE bottomWdw (wdwPtr : ptrWdwSlot);
  974.   VAR r : Rectangle;
  975. BEGIN
  976.   WITH wdwPtr^ DO
  977.     IF (onlyOneTop >= 0) & (wdw = onlyOneTop) 
  978.     THEN
  979.       (* Alle nach hinten schicken *)
  980.     ELSE
  981.       untopWdw (wdwPtr);
  982.       MagicAES.WindSet (wdw, MagicAES.WFBOTTOM, r);
  983.       BringToBottom (wdw, mtAppl.ApplIdent);
  984.       (*
  985.       BottomOfQueue (r.x, r.y);
  986.       IF r.x # wdw
  987.       THEN
  988.         TopLastWindow();
  989.       END;
  990.       *)
  991.     END;
  992.   END;
  993. END bottomWdw;
  994.  
  995. PROCEDURE SendRedraw (win: INTEGER; r : Rectangle); FORWARD;
  996.  
  997. PROCEDURE moveSizeWdw (wdwPtr : ptrWdwSlot; sized, fulled : BOOLEAN; newSize : Rectangle; adaptPos : BOOLEAN);
  998. (* Wird aufgerufen, wenn das Fenster verschoben 
  999.  * oder in der Gr”že ver„ndert wird.
  1000.  *)
  1001.   VAR docChanged : BOOLEAN;
  1002.       oldVal     : LONGINT;
  1003.       idx        : INTEGER;
  1004.       again      : BOOLEAN;
  1005. BEGIN
  1006.   WITH wdwPtr^ DO
  1007.     IF ~isIcon
  1008.     THEN
  1009.       newSize.w := BinOps.HigherInt (newSize.w, minWindWidth);
  1010.       newSize.h := BinOps.HigherInt (newSize.h, minWindHeight);
  1011.       (* Workarea aus neuer Gr”že berechnen *)
  1012.       MagicAES.WindCalc (MagicAES.WCWORK, comps, newSize, wdwWork);
  1013.       IF snap 
  1014.       THEN
  1015.         hdlSnap (wdw, vdi, special, wdwWork);
  1016.       END;
  1017.       (* Jetzt neue Aužengr”že berechnen *)
  1018.       MagicAES.WindCalc (MagicAES.WCBORDER, comps, wdwWork, newSize);
  1019.       IF sized & ~fulled THEN isFull := FALSE; END;
  1020.     END;
  1021.     IF ~isHidden
  1022.     THEN
  1023.       idx := 1;
  1024.       LOOP
  1025.         MagicAES.WindSet(wdw, MagicAES.WFCURRXYWH, newSize);
  1026.         again := FALSE;
  1027.         IF ~isIcon
  1028.         THEN
  1029.           MagicAES.WindGet(wdw, MagicAES.WFCURRXYWH, wdwCurr);
  1030.           IF (wdwCurr.w # newSize.w) 
  1031.           THEN
  1032.             INC (newSize.w, idx*mtAppl.CharWidth);
  1033.             again := TRUE;
  1034.           END;
  1035.           IF (wdwCurr.h # newSize.h) 
  1036.           THEN
  1037.             INC (newSize.h, idx*mtAppl.CharHeight);
  1038.             again := TRUE;
  1039.           END;
  1040.           IF again
  1041.           THEN
  1042.             INC (idx);
  1043.             (* Workarea aus neuer Gr”že berechnen *)
  1044.             MagicAES.WindCalc (MagicAES.WCWORK, comps, newSize, wdwWork);
  1045.             IF snap 
  1046.             THEN
  1047.               hdlSnap (wdw, vdi, special, wdwWork);
  1048.             END;
  1049.             (* Jetzt neue Aužengr”že berechnen *)
  1050.             MagicAES.WindCalc (MagicAES.WCBORDER, comps, wdwWork, newSize);
  1051.           ELSE
  1052.             EXIT
  1053.           END;
  1054.         ELSE
  1055.           EXIT
  1056.         END;
  1057.       END;
  1058.     END;
  1059.     wdwCurr := newSize;
  1060.     IF ~isIcon & ~isHidden
  1061.     THEN
  1062.       (* Neuen Arbeitsbereich holen *)
  1063.       wdwGetScroll (wdw, vdi, special, wdwWork);
  1064.       IF sized & adaptPos THEN
  1065.         (* Falls Dokument ganz hineinpažt, neu positionieren *)
  1066.         docChanged := FALSE;
  1067.         IF document.y > 0
  1068.         THEN
  1069.           IF LONG (wdwWork.h) DIV yFactor + document.y > document.h
  1070.           THEN
  1071.             oldVal := document.y;
  1072.             document.y := BinOps.HigherLInt (0, document.h - (LONG(wdwWork.h) DIV yFactor)+1);
  1073.             docChanged := oldVal # document.y;
  1074.           END;
  1075.         END;
  1076.         IF document.x > 0
  1077.         THEN
  1078.           IF LONG (wdwWork.w) DIV xFactor + document.x > document.w
  1079.           THEN
  1080.             oldVal := document.x;
  1081.             document.x := BinOps.HigherLInt (0, document.w - (LONG (wdwWork.w) DIV xFactor));
  1082.             docChanged := docChanged OR (oldVal # document.x);
  1083.           END;
  1084.         END;
  1085.         IF docChanged
  1086.         THEN
  1087.           setNewWdw (wdw, vdi, special, document, FALSE);
  1088.           (* Redraw ausl”sen ber Fensterbereich *)
  1089.           SendRedraw (wdw, newSize);
  1090.         END;
  1091.         (* Slider neu berechnen *)
  1092.         CalcVSlider (wdwPtr);
  1093.         CalcHSlider (wdwPtr);
  1094.       END;
  1095.     END;
  1096.   END;
  1097. END moveSizeWdw;
  1098.  
  1099. PROCEDURE fullWdw (wdwPtr : ptrWdwSlot);
  1100. (* Wird aufgerufen, wenn fr das Fenster ein FULL-Event
  1101.  * auftrat. Gegebenenfalls wird noch die Snap-Prozedur 
  1102.  * aufgerufen.
  1103.  * Die Slider werden neu berechnet.
  1104.  *)
  1105.  VAR newSize : Rectangle;
  1106. BEGIN
  1107.   WITH wdwPtr^ DO
  1108.     IF isIcon OR isHidden OR (wdwDial # NIL) THEN RETURN END;
  1109.     IF isFull
  1110.     THEN
  1111.       newSize := wdwLast;
  1112.     ELSE
  1113.       newSize := wdwFull;
  1114.       wdwLast := wdwCurr;
  1115.     END;
  1116.     isFull := ~isFull;
  1117.     (* Jetzt der Einfachheit halber einfach moveSize aufrufen *)
  1118.     moveSizeWdw (wdwPtr, TRUE, TRUE, newSize, TRUE);
  1119.   END;
  1120. END fullWdw;
  1121.  
  1122. PROCEDURE arrowedWdw (wdwPtr : ptrWdwSlot; what : CARDINAL; amount: INTEGER);
  1123. VAR button : BITSET;
  1124.     scrollProc : PROCEDURE (ptrWdwSlot, INTEGER);
  1125. BEGIN
  1126.   CASE what OF
  1127.     0 : scrollProc := pageUp; |
  1128.     1 : scrollProc := pageDown; |
  1129.     2 : scrollProc := scrollUp; |
  1130.     3 : scrollProc := scrollDown; |
  1131.     4 : scrollProc := pageLeft; |
  1132.     5 : scrollProc := pageRight; |
  1133.     6 : scrollProc := scrollLeft; |
  1134.     7 : scrollProc := scrollRight; |
  1135.   ELSE
  1136.   END;
  1137.   IF (what >= 0) & (what <= 7) THEN
  1138.     WITH wdwPtr^ DO
  1139.       hdlUpdate (wdw, vdi, special, TRUE);
  1140.       scrollProc (wdwPtr, amount);
  1141.       (*
  1142.       REPEAT
  1143.         scrollProc (wdwPtr, 1);
  1144.         MagicAES.GrafMkstate(v.int, v.int, button, v.bset);
  1145.       UNTIL ~(0 IN button);
  1146.       *)
  1147.       hdlUpdate (wdw, vdi, special, FALSE);
  1148.     END;
  1149.   END;
  1150. END arrowedWdw;
  1151.  
  1152. PROCEDURE vSlideWdw (wdwPtr : ptrWdwSlot; where: CARDINAL);
  1153. VAR oldStart : LONGINT;
  1154.     newStart : LONGINT;
  1155. BEGIN
  1156.   WITH wdwPtr^ DO 
  1157.     oldStart := document.y;                      (* Start des Ausschnittes merken *)
  1158.     IF (document.h+1) * yFactor > LONG(wdwWork.h) THEN
  1159.       IF where = 1000 THEN
  1160.         document.y := ((document.h+1)*yFactor-LONG(wdwWork.h)) DIV yFactor;
  1161.       ELSE
  1162.         document.y := (VAL(LONGINT,where)*(((document.h+1)*yFactor)-LONG(wdwWork.h)) DIV 1000L) DIV yFactor;
  1163.       END;
  1164.       IF oldStart # document.y THEN
  1165.         hdlUpdate (wdw, vdi, special, TRUE);
  1166.         setNewWdw (wdw, vdi, special, document, TRUE);
  1167.         IF oldStart < document.y
  1168.         THEN
  1169.           scrollWdw (wdwPtr, DOWN, (document.y-oldStart) * yFactor);
  1170.         ELSE
  1171.           scrollWdw (wdwPtr, UP, (oldStart-document.y) * yFactor);
  1172.         END;
  1173.         hdlUpdate (wdw, vdi, special, FALSE);
  1174.       END
  1175.     END;
  1176.     CalcVSlider (wdwPtr);
  1177.   END
  1178. END vSlideWdw;
  1179.  
  1180. PROCEDURE hSlideWdw (wdwPtr : ptrWdwSlot; where : INTEGER);
  1181. VAR oldOff,
  1182.     newOff : LONGINT;
  1183. BEGIN
  1184.   WITH wdwPtr^ DO
  1185.     oldOff := document.x;
  1186.     IF (document.w+1) * xFactor > LONG(wdwWork.w) THEN
  1187.       IF where = 1000 THEN
  1188.         newOff := (document.w+1) * xFactor - LONG(wdwWork.w);
  1189.       ELSE
  1190.         newOff :=  LONG(where) * ((document.w+1) * xFactor - LONG(wdwWork.w)) DIV 1000L;
  1191.       END;
  1192.       newOff := BinOps.LowerLInt (newOff, ((document.w+1) * xFactor)-LONG(wdwWork.w));
  1193.       IF newOff # oldOff THEN
  1194.         hdlUpdate (wdw, vdi, special, TRUE);
  1195.         document.x := newOff DIV xFactor;
  1196.         setNewWdw (wdw, vdi, special, document, TRUE);
  1197.         IF oldOff < newOff
  1198.         THEN
  1199.           scrollLR (wdwPtr, RIGHT, SHORT(newOff-oldOff));
  1200.         ELSE
  1201.           scrollLR (wdwPtr, LEFT, SHORT(oldOff-newOff));
  1202.         END;
  1203.         hdlUpdate (wdw, vdi, special, FALSE);
  1204.       END;
  1205.     END;
  1206.     CalcHSlider (wdwPtr);
  1207.   END
  1208. END hSlideWdw;
  1209.  
  1210. PROCEDURE hideWdw (wdwPtr: ptrWdwSlot);
  1211. BEGIN
  1212.   WITH wdwPtr^ DO
  1213.     (* Fenster schliežen *)
  1214.     MagicAES.WindClose (wdw);
  1215.     IF hdlHide # hideProc (NIL) THEN hdlHide (wdw, vdi, special, TRUE); END;
  1216.     isHidden := TRUE;
  1217.   END;
  1218. END hideWdw;
  1219.  
  1220. PROCEDURE showWdw (wdwPtr : ptrWdwSlot; doUntop: BOOLEAN);
  1221.   VAR bits : INTEGER;
  1222.       r    : Rectangle;
  1223.       oldTop: ptrWdwSlot;
  1224. BEGIN
  1225.   WITH wdwPtr^ DO
  1226.     (* Altes TopWindow untoppen *)
  1227.     oldTop := FindTop();
  1228.     IF ((oldTop # NIL) & doUntop) THEN
  1229.       untopWdw (oldTop);
  1230.     END;
  1231.     (* Fenster wieder ”ffnen *)
  1232.     isHidden := FALSE;
  1233.     IF hdlHide # hideProc (NIL) THEN hdlHide (wdw, vdi, special, FALSE); END;
  1234.     MagicAES.WindOpen (wdw, wdwCurr);
  1235.     IF hdlTop (wdw, vdi, special) THEN END;
  1236.     isTop := TRUE;
  1237.     (* Die Slider wieder richtig setzen *)
  1238.     IF (MagicAES.VSLIDE IN comps) THEN 
  1239.       MagicAES.WindSet (wdw, MagicAES.WFVSLSIZE, Rectangle {VslSize, 0,0,0});
  1240.       MagicAES.WindSet (wdw, MagicAES.WFVSLIDE, Rectangle {VslPos, 0,0,0});
  1241.     END;
  1242.     IF (MagicAES.HSLIDE IN comps) THEN 
  1243.       MagicAES.WindSet (wdw, MagicAES.WFHSLSIZE, Rectangle {HslSize, 0,0,0});
  1244.       MagicAES.WindSet (wdw, MagicAES.WFHSLIDE, Rectangle {HslPos, 0,0,0});
  1245.     END;
  1246.     (* Jetzt noch abfragen, ob das Fenster iconifiziert ist *)
  1247.     isIcon := FALSE;
  1248.     IF (MagicAES.ApplGetinfo (MagicAES.AEWINDOWS, bits, v.int, v.int, v.int) = 1)
  1249.      & (MagicSys.Bit7 IN BITSET(bits))
  1250.     THEN
  1251.       MagicAES.WindGet (wdw, MagicAES.WFICONIFY, r);
  1252.       isIcon := r.x = 1;
  1253.     END;
  1254.   END;
  1255. END showWdw;
  1256.  
  1257. PROCEDURE closeWdw (wdwPtr : ptrWdwSlot; force : BOOLEAN) : BOOLEAN;
  1258. BEGIN
  1259.   (* CloseProc aufrufen *)
  1260.   WITH wdwPtr^ DO
  1261.     IF ~hdlClose (wdw, vdi, special, force)
  1262.     THEN
  1263.       RETURN FALSE
  1264.     END;
  1265.     (* Fenster schliežen *)
  1266.     IF ~isHidden
  1267.     THEN
  1268.       MagicAES.WindClose (wdw);
  1269.     END;
  1270.     MagicAES.WindDelete (wdw);
  1271.     WindowIsClosed (wdw);
  1272.     (* Workstation schliežen *)
  1273.     IF vdi > 0 
  1274.     THEN
  1275.       mtAppl.CloseWorkstation (vdi);
  1276.       vdi := -1;
  1277.     END;
  1278.   END;
  1279.   (* Aus der Liste aush„ngen *)
  1280.   IF wdwPtr^.next # NIL
  1281.   THEN
  1282.     wdwPtr^.next^.prev := wdwPtr^.prev;
  1283.   END;
  1284.   IF wdwPtr^.prev # NIL
  1285.   THEN
  1286.     wdwPtr^.prev^.next := wdwPtr^.next;
  1287.   END;
  1288.   IF windows = wdwPtr 
  1289.   THEN
  1290.     windows := wdwPtr^.next;
  1291.   END;
  1292.   IF wdwPtr^.onlyTop
  1293.   THEN
  1294.     onlyOneTop := wdwPtr^.lastOnlyTop;
  1295.   END;
  1296.   DISPOSE (wdwPtr);
  1297.   
  1298.   (* Neues TopWindow toppen (WMNEWTOP bzw. WMONTOP in AES 4.0 *)
  1299.   wdwPtr := FindTop ();
  1300.   IF (wdwPtr # NIL) (* & ~multiTOS *)
  1301.   THEN
  1302.     topWdw (wdwPtr, FALSE);
  1303.   END;
  1304.   RETURN TRUE
  1305. END closeWdw;
  1306.  
  1307. PROCEDURE iconifyWdw (wdwPtr : ptrWdwSlot; iconRect : Rectangle);
  1308. BEGIN
  1309.   WITH wdwPtr^ DO
  1310.     IF isIcon THEN RETURN END;
  1311.     isIcon := TRUE;
  1312.     wdwIcon := wdwCurr;
  1313.     MagicAES.WindSet (wdw, MagicAES.WFICONIFY, iconRect);
  1314.     MagicAES.WindGet (wdw, MagicAES.WFCURRXYWH, wdwCurr);
  1315.     IF hdlHide # hideProc (NIL) THEN hdlHide (wdw, vdi, special, TRUE); END;
  1316.     FullRedrawWdw (wdw);
  1317.   END;
  1318. END iconifyWdw;
  1319.  
  1320. PROCEDURE unIconifyWdw (wdwPtr : ptrWdwSlot; wdwRect : Rectangle);
  1321.   VAR p : ptrWdwSlot;
  1322.       curr : Rectangle;
  1323. BEGIN
  1324.   WITH wdwPtr^ DO
  1325.     IF allIconified
  1326.     THEN
  1327.       (* alle anderen versteckten, iconifizierten wieder zeigen bis auf 
  1328.        * dieses wdw!
  1329.        *)
  1330.       p := windows; 
  1331.       WHILE p # NIL DO
  1332.         IF (p^.wdw # wdwPtr^.wdw) &
  1333.            p^.isIcon & p^.isHidden
  1334.         THEN
  1335.           (* ist nicht dieses Window *)
  1336.           showWdw (p, FALSE);
  1337.           MagicAES.WindGet (p^.wdw, MagicAES.WFCURRXYWH, curr);
  1338.           moveSizeWdw (p, FALSE, FALSE, curr, FALSE);
  1339.         END;
  1340.         p := p^.next;
  1341.       END;
  1342.       allIconified := FALSE;
  1343.     END;
  1344.     IF ~isIcon THEN RETURN END;
  1345.     isIcon := FALSE;
  1346.     MagicAES.WindSet (wdw, MagicAES.WFUNICONIFY, wdwRect);
  1347.     MagicAES.WindGet (wdw, MagicAES.WFCURRXYWH, wdwCurr);
  1348.     IF hdlHide # hideProc(NIL) THEN hdlHide (wdw, vdi, special, FALSE); END;
  1349.     moveSizeWdw (wdwPtr, FALSE, FALSE, wdwCurr,FALSE);
  1350.     IF (MagicAES.VSLIDE IN wdwPtr^.comps) THEN 
  1351.       MagicAES.WindSet (wdw, MagicAES.WFVSLSIZE, Rectangle {VslSize, 0,0,0});
  1352.       MagicAES.WindSet (wdw, MagicAES.WFVSLIDE, Rectangle {VslPos, 0,0,0});
  1353.     END;
  1354.     IF (MagicAES.HSLIDE IN wdwPtr^.comps) THEN 
  1355.       MagicAES.WindSet (wdw, MagicAES.WFHSLSIZE, Rectangle {HslSize, 0,0,0});
  1356.       MagicAES.WindSet (wdw, MagicAES.WFHSLIDE, Rectangle {HslPos, 0,0,0});
  1357.     END;
  1358.     topWdw (wdwPtr, TRUE);
  1359.     SendTop (wdwPtr^.wdw, mtAppl.ApplIdent);
  1360.   END;
  1361. END unIconifyWdw;
  1362.  
  1363. PROCEDURE allIconifyWdw (wdwPtr : ptrWdwSlot; iconRect : Rectangle);
  1364.   VAR p : ptrWdwSlot;
  1365. BEGIN
  1366.   (* Das angeklickte Window wird iconifiziert und alle anderen werden versteckt.
  1367.    * Schon versteckte werden beim uniconify nicht mit aufgedeckt! 
  1368.    *)
  1369.   p := windows; 
  1370.   WHILE p # NIL DO
  1371.     IF ~p^.isHidden (* & ~p^.isIcon *) & (p^.wdw # wdwPtr^.wdw)
  1372.     THEN
  1373.       (* ist nicht dieses Window *)
  1374.       p^.wdwIcon := p^.wdwCurr;
  1375.       hideWdw (p);
  1376.       p^.isIcon := TRUE;
  1377.     ELSIF ~p^.isHidden (* & ~p^.isIcon *) & (p^.wdw = wdwPtr^.wdw)
  1378.     THEN
  1379.       iconifyWdw (p, iconRect);
  1380.     END;
  1381.     p := p^.next;
  1382.   END;
  1383.   allIconified := TRUE;
  1384. END allIconifyWdw;
  1385.  
  1386. (* Diese Prozedur handelt den ganzen Drag-Drop Kram nach einem Event *)
  1387. PROCEDURE HandleDragDrop (mess: ADDRESS);
  1388. CONST   cPipeName   = 'u:\pipe\dragdrop.';
  1389.   VAR access : POINTER TO RECORD
  1390.                  messId : INTEGER;
  1391.                  apId   : INTEGER;
  1392.                  over   : INTEGER;
  1393.                  tWin   : INTEGER;
  1394.                  mx     : INTEGER;
  1395.                  my     : INTEGER;
  1396.                  kshift : INTEGER;
  1397.                  pext0,
  1398.                  pext1  : CHAR;
  1399.                END;
  1400.       buff  : ARRAY [0..MagicAES.DD_EXTSIZE] OF CHAR;
  1401.       hdr   : POINTER TO RECORD
  1402.                 dtype : ARRAY [0..3] OF CHAR;
  1403.                 dlen  : LONGCARD;
  1404.                 dname : ARRAY [0..2047] OF CHAR;
  1405.               END;
  1406.      oldsigpipe : ADDRESS;
  1407.      i          : INTEGER;
  1408.      pext       : ARRAY [0..3] OF CHAR;
  1409.      exts       : ARRAY [0..MagicAES.DD_EXTSIZE - 1] OF CHAR;
  1410.      pname      : ARRAY [0..255] OF CHAR;
  1411.      phdl       : INTEGER;
  1412.      data       : ADDRESS;
  1413.      count      : LONGCARD;
  1414.      hdrLen     : CARDINAL;
  1415.      wdw        : INTEGER;
  1416.      
  1417.  
  1418. PROCEDURE restore();
  1419. BEGIN 
  1420.   (* Alten Sigpipe-Handler wieder installieren *)
  1421.   IF phdl > 0 THEN v.int := MagicDOS.Fclose (phdl); END;
  1422.   (* Speicher wird hier freigegeben *)
  1423.   IF data # NIL THEN DEALLOCATE (data, 0); END;
  1424.   IF hdr # NIL THEN DEALLOCATE (hdr, 0); END;
  1425.   oldsigpipe := Mintbind.Psignal (Mintbind.SIGPIPE, oldsigpipe);
  1426. END restore;
  1427.  
  1428. BEGIN
  1429.   phdl := -1;
  1430.   hdr := NIL;
  1431.   data := NIL;
  1432.   (* Erstmal neuen Signalhandler installieren *)
  1433.   oldsigpipe := Mintbind.Psignal (Mintbind.SIGPIPE, Mintbind.SIG_IGN);
  1434.  
  1435.   access := mess;
  1436.   WITH access^ DO
  1437.     pext[0] := pext0;
  1438.     pext[1] := pext1;
  1439.     pext[2] := 0C;
  1440.     Strings.Assign (cPipeName, pname, v.bool);
  1441.     Strings.Append (pext, pname, v.bool);
  1442.     phdl := MagicDOS.Fopen (pname, {MagicDOS.ReadWrite});
  1443.     IF phdl < 0 THEN restore(); RETURN END;
  1444.     (* Pipe ist offen, jetzt erstmal beim Windowhandler anfragen, ob 
  1445.      * das Targetfenster DragDrop versteht
  1446.      *)
  1447.     IF ~WdwDoesDragDrop (tWin)
  1448.     THEN
  1449.       (* Das Fenster kann kein DragDrop, also nehmen wir auch nichts an!
  1450.        *)
  1451.       buff[0] := CHR(MagicAES.DD_NAK);
  1452.       count := 1;
  1453.       MagicDOS.Fwrite (phdl, count, ADR(buff));
  1454.       (* Uns ist ziemlich egal, ob das geklappt hat, wir schliežen die Pipe 
  1455.        * jetzt wieder 
  1456.        *)
  1457.       v.int := MagicDOS.Fclose (phdl);
  1458.       restore();
  1459.       RETURN 
  1460.     END;
  1461.     (* Ok, das Fenster kann Drag & Drop, also jetzt mal die Extensions anfordern 
  1462.      *)
  1463.     wdw := tWin;
  1464.     WdwDDGetExts (wdw, exts);
  1465.     (* Umkopieren *)
  1466.     FOR i := 0 TO SHORT(MagicAES.DD_EXTSIZE) - 1 DO
  1467.       buff[i+1] := exts[i];
  1468.     END;
  1469.     buff[0] := CHR (MagicAES.DD_OK);
  1470.     (* Jetzt DD_OK und Extensions in Pipe schreiben *)
  1471.     count := MagicAES.DD_EXTSIZE + 1;
  1472.     MagicDOS.Fwrite (phdl, count, ADR(buff));
  1473.     IF count # (MagicAES.DD_EXTSIZE + 1)
  1474.     THEN
  1475.       (* Fehler aufgetreten, Pipe schliežen und raus hier. *)
  1476.       restore ();
  1477.       RETURN
  1478.     END;
  1479.     LOOP
  1480.       (* Jetzt 2 Bytes aus der Pipe lesen (Headerl„nge) *)
  1481.       count := 2;
  1482.       MagicDOS.Fread (phdl, count, ADR(hdrLen)); 
  1483.       IF count # 2
  1484.       THEN
  1485.         (* Fehler aufgetreten, Pipe schliežen und raus hier. *)
  1486.         EXIT
  1487.       END;
  1488.       (* Jetzt den Header lesen *)
  1489.       ALLOCATE (hdr, hdrLen);
  1490.       IF hdr = NIL
  1491.       THEN
  1492.         (* Kein Speicher frei! *)
  1493.         EXIT
  1494.       END;
  1495.       (* Jetzt den Header lesen *)
  1496.       count := hdrLen;
  1497.       MagicDOS.Fread (phdl, count, hdr); 
  1498.       IF count # LONG(hdrLen)
  1499.       THEN
  1500.         (* Fehler aufgetreten, Pipe schliežen und raus hier. *)
  1501.         EXIT
  1502.       END;
  1503.       (* Jetzt haben wir den Header, nachfragen, ob das akzeptiert wird *)
  1504.       IF WdwDDAcceptData (wdw, hdr)
  1505.       THEN
  1506.         (* Speicher allozieren fr Daten *)
  1507.         ALLOCATE (data, hdr^.dlen);
  1508.         IF data = NIL
  1509.         THEN
  1510.           (* DD_NAK in Pipe schreiben und abbrechen *)
  1511.           buff[0] := CHR (MagicAES.DD_NAK);
  1512.           count := 1;
  1513.           MagicDOS.Fwrite (phdl, count, ADR(buff));
  1514.           EXIT
  1515.         END;
  1516.         (* DD_OK in Pipe schreiben *)
  1517.         buff[0] := CHR (MagicAES.DD_OK);
  1518.         count := 1;
  1519.         MagicDOS.Fwrite (phdl, count, ADR(buff));
  1520.         IF count # 1 
  1521.         THEN
  1522.           EXIT
  1523.         END;
  1524.         (* Ok, jetzt haben wir auch einen Buffer fr die Daten,
  1525.          * jetzt k”nnen wir die Daten aus der Pipe lesen 
  1526.          *)
  1527.         count := hdr^.dlen;
  1528.         MagicDOS.Fread (phdl, count, data);
  1529.         IF count # hdr^.dlen 
  1530.         THEN 
  1531.           EXIT 
  1532.         END;
  1533.         (* Jetzt die Daten an das Fenster bergeben *)
  1534.         WdwDDWriteData (wdw, data, count);
  1535.         (* Speicher wieder am Ende in restore freigeben *)
  1536.         (* Das war's, Pipe wird am Ende geschlossen *)
  1537.         EXIT
  1538.       ELSE
  1539.         (* DD_EXT in Pipe schreiben und wieder nach vorne *)
  1540.         buff[0] := CHR (MagicAES.DD_EXT);
  1541.         count := 1;
  1542.         MagicDOS.Fwrite (phdl, count, ADR(buff));
  1543.       END;
  1544.       DEALLOCATE (hdr, 0);
  1545.     END; (* LOOP *)
  1546.   END;
  1547.   restore();
  1548. END HandleDragDrop;
  1549.  
  1550. PROCEDURE MessageEvent (PBuff : ADDRESS) : BOOLEAN;
  1551. VAR mess   : POINTER TO ARRAY[0..15] OF INTEGER;
  1552.     wdwPtr : ptrWdwSlot;
  1553.     voidO  : BOOLEAN;
  1554. BEGIN
  1555.   mess := PBuff;
  1556.   wdwPtr := FindWindow (mess^[3]);
  1557.   IF wdwPtr # NIL 
  1558.   THEN 
  1559.     WITH wdwPtr^ DO
  1560.       CASE mess^[0] OF
  1561.         MagicAES.WMREDRAW  : updateWdw (wdwPtr, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}); |
  1562.         MagicAES.WMTOPPED  : topWdw (wdwPtr, TRUE); |
  1563.         MagicAES.WMCLOSED  : voidO := closeWdw (wdwPtr, FALSE); |
  1564.         MagicAES.WMFULLED  : fullWdw (wdwPtr); |
  1565.         MagicAES.WMARROWED : IF mess^[5] >= 0
  1566.                              THEN 
  1567.                                arrowedWdw (wdwPtr, mess^[4], 1); 
  1568.                              END;
  1569.                              IF mess^[5] < 0
  1570.                              THEN
  1571.                                (* erweiterte Scrollfunktionen von Winx *)
  1572.                                arrowedWdw (wdwPtr, mess^[4], -mess^[5])
  1573.                              END;
  1574.                              IF mess^[7] < 0
  1575.                              THEN
  1576.                                (* erweiterte Scrollfunktionen von Winx *)
  1577.                                arrowedWdw (wdwPtr, mess^[6], -mess^[7])
  1578.                              END;|
  1579.         MagicAES.WMHSLID   : hSlideWdw (wdwPtr, mess^[4]); |
  1580.         MagicAES.WMVSLID   : vSlideWdw (wdwPtr, mess^[4]); |
  1581.         MagicAES.WMSIZED   : moveSizeWdw (wdwPtr, TRUE, FALSE, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}, TRUE); |
  1582.         MagicAES.WMMOVED   : moveSizeWdw (wdwPtr, FALSE, FALSE, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}, FALSE); |
  1583.         MagicAES.WMNEWTOP  : topWdw (wdwPtr, FALSE); |
  1584.         MagicAES.WMUNTOPPED: untopWdw (wdwPtr);     |
  1585.         MagicAES.WMONTOP   : topWdw (wdwPtr, FALSE); |
  1586.         MagicAES.WMBDROPPED: backdropWdw (wdwPtr); |
  1587.         MagicAES.WMBOTTOMED: bottomWdw (wdwPtr); |
  1588.         MagicAES.WMICONIFY : iconifyWdw (wdwPtr, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}); |
  1589.         MagicAES.WMUNICONIFY  : unIconifyWdw (wdwPtr, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}); |
  1590.         MagicAES.WMALLICONIFY : allIconifyWdw (wdwPtr, Rectangle {mess^[4], mess^[5], mess^[6], mess^[7]}); |
  1591.         MagicAES.AP_DRAGDROP  : HandleDragDrop (PBuff); |
  1592.       ELSE
  1593.         RETURN FALSE;
  1594.       END;
  1595.       RETURN TRUE;
  1596.     END 
  1597.   ELSE
  1598.     (* Feststellen, ob ein anderes Fenster getoppt wurde *)
  1599.     IF mess^[0] = MagicAES.WMTOPPED
  1600.     THEN
  1601.       (* Feststellen, ob eines unserer Fenster Topwindow war
  1602.        * und ggf. untoppedHdler aufrufen
  1603.        *)
  1604.       (* altes Top-Window feststellen *)
  1605.       wdwPtr := FindTop ();
  1606.       IF wdwPtr # NIL THEN
  1607.         WITH wdwPtr^ DO
  1608.           isTop := FALSE;
  1609.           IF hdlUntop # untopProc (NIL)
  1610.           THEN
  1611.             hdlUntop (wdw, vdi, special);
  1612.           END;
  1613.         END;
  1614.       END;
  1615.     END;
  1616.   END;
  1617.   RETURN FALSE;
  1618. END MessageEvent;
  1619.  
  1620. TYPE pageProc = PROCEDURE (ptrWdwSlot, INTEGER);
  1621.  
  1622. PROCEDURE scrollFunction (wdw : INTEGER; func : pageProc; parm : INTEGER);
  1623.   VAR wdwPtr : ptrWdwSlot;
  1624. BEGIN
  1625.   wdwPtr := FindWindow (wdw);
  1626.   IF wdwPtr # NIL
  1627.   THEN
  1628.     WITH wdwPtr^ DO
  1629.       hdlUpdate (wdw, vdi, special, TRUE);
  1630.       func (wdwPtr, parm);
  1631.       hdlUpdate (wdw, vdi, special, FALSE);
  1632.     END;
  1633.   END;
  1634. END scrollFunction;
  1635.  
  1636. (*====================================================*
  1637.  *                                                    *
  1638.  *   Exportierte Funktionen                           *
  1639.  *                                                    *
  1640.  *====================================================*)
  1641.  
  1642. PROCEDURE PageUp (wdw : INTEGER);
  1643. BEGIN
  1644.   scrollFunction (wdw, pageUp, 1);
  1645. END PageUp;
  1646.  
  1647. PROCEDURE PageDown (wdw : INTEGER);
  1648. BEGIN
  1649.   scrollFunction (wdw, pageDown, 1);
  1650. END PageDown;
  1651.  
  1652. PROCEDURE PageLeft (wdw : INTEGER);
  1653. BEGIN
  1654.   scrollFunction (wdw, pageLeft, 1);
  1655. END PageLeft;
  1656.  
  1657. PROCEDURE PageRight (wdw : INTEGER);
  1658. BEGIN
  1659.   scrollFunction (wdw, pageRight, 1);
  1660. END PageRight;
  1661.  
  1662. PROCEDURE ScrollUp     (wdw : INTEGER; lines : INTEGER);
  1663. BEGIN
  1664.   scrollFunction (wdw, scrollUp, lines);
  1665. END ScrollUp;
  1666.  
  1667. PROCEDURE ScrollDown   (wdw : INTEGER; lines : INTEGER);
  1668. BEGIN
  1669.   scrollFunction (wdw, scrollDown, lines);
  1670. END ScrollDown;
  1671.  
  1672. PROCEDURE ScrollLeft   (wdw : INTEGER; amount : INTEGER);
  1673. BEGIN
  1674.   scrollFunction (wdw, scrollLeft, amount);
  1675. END ScrollLeft;
  1676.  
  1677. PROCEDURE ScrollRight  (wdw : INTEGER; amount : INTEGER);
  1678. BEGIN
  1679.   scrollFunction (wdw, scrollRight, amount);
  1680. END ScrollRight;
  1681.  
  1682. PROCEDURE WdwComps (wdw : INTEGER) : BITSET;
  1683. (* Liefert die Window-Elemente zurck 
  1684.  *)
  1685.   VAR wdwPtr : ptrWdwSlot;
  1686. BEGIN
  1687.   wdwPtr := FindWindow (wdw);
  1688.   IF wdwPtr # NIL
  1689.   THEN
  1690.     RETURN wdwPtr^.comps;
  1691.   END;
  1692.   RETURN {};
  1693. END WdwComps;
  1694.  
  1695. PROCEDURE SnapWdw (wdw : INTEGER);
  1696.   VAR wdwPtr : ptrWdwSlot;
  1697. BEGIN
  1698.   wdwPtr := FindWindow (wdw);
  1699.   IF wdwPtr # NIL
  1700.   THEN
  1701.     moveSizeWdw (wdwPtr, FALSE, FALSE, wdwPtr^.wdwCurr, FALSE);
  1702.   END;
  1703. END SnapWdw;
  1704.  
  1705. PROCEDURE SetWdwSize (wdw : INTEGER; rect : Rectangle);
  1706. (* Setzt neue aktuelle Aužengr”že fr das Fenster
  1707.  *)
  1708.   VAR wdwPtr : ptrWdwSlot;
  1709. BEGIN
  1710.   wdwPtr := FindWindow (wdw);
  1711.   IF wdwPtr # NIL
  1712.   THEN
  1713.     moveSizeWdw (wdwPtr, TRUE, FALSE, rect, FALSE);
  1714.   END;
  1715. END SetWdwSize;
  1716.  
  1717. PROCEDURE GetWdwSize (wdw : INTEGER; VAR rect : Rectangle);
  1718. (* Erfragt aktuelle Aužengr”že fr das Fenster
  1719.  *)
  1720.   VAR wdwPtr : ptrWdwSlot;
  1721. BEGIN
  1722.   wdwPtr := FindWindow (wdw);
  1723.   IF wdwPtr # NIL
  1724.   THEN
  1725.     IF wdwPtr^.isIcon
  1726.     THEN
  1727.       rect := wdwPtr^.wdwIcon;
  1728.     ELSE
  1729.       rect := wdwPtr^.wdwCurr;
  1730.     END;
  1731.   ELSE
  1732.     MagicAES.WindGet (wdw, MagicAES.WFCURRXYWH, rect);
  1733.   END;
  1734. END GetWdwSize;
  1735.  
  1736. PROCEDURE SetWdwWork (wdw : INTEGER; rect : Rectangle);
  1737. (* Setzt neue aktuelle Arbeitsfl„chengr”že fr das Fenster
  1738.  *)
  1739.   VAR wdwPtr : ptrWdwSlot;
  1740. BEGIN
  1741.   wdwPtr := FindWindow (wdw);
  1742.   IF wdwPtr # NIL
  1743.   THEN
  1744.     MagicAES.WindCalc (MagicAES.WCBORDER, wdwPtr^.comps, rect, rect);
  1745.     moveSizeWdw (wdwPtr, TRUE, FALSE, rect, FALSE);
  1746.   END;
  1747. END SetWdwWork;
  1748.  
  1749. PROCEDURE GetWdwWork (wdw : INTEGER; VAR rect : Rectangle);
  1750. (* Erfragt aktuelle Arbeitsfl„chengr”že fr das Fenster
  1751.  *)
  1752.   VAR wdwPtr : ptrWdwSlot;
  1753. BEGIN
  1754.   wdwPtr := FindWindow (wdw);
  1755.   IF wdwPtr # NIL
  1756.   THEN
  1757.     rect := wdwPtr^.wdwCurr;
  1758.     MagicAES.WindCalc (MagicAES.WCWORK, wdwPtr^.comps, rect, rect);
  1759.   ELSE
  1760.     MagicAES.WindGet (wdw, MagicAES.WFWORKXYWH, rect);
  1761.   END;
  1762. END GetWdwWork;
  1763.  
  1764. PROCEDURE SetDocumentParms (wdw : INTEGER; xFac, yFac: LONGINT);
  1765. (* Setzt die Parameter fr die Ausschnittsberechnung 
  1766.  *)
  1767.   VAR wdwPtr : ptrWdwSlot;
  1768. BEGIN
  1769.   wdwPtr := FindWindow (wdw);
  1770.   IF wdwPtr # NIL
  1771.   THEN
  1772.     WITH wdwPtr^ DO
  1773.       IF xFac # xFactor THEN xFactor := xFac; CalcHSlider (wdwPtr); END;
  1774.       IF yFac # yFactor THEN yFactor := yFac; CalcVSlider (wdwPtr); END;
  1775.     END;
  1776.   END;
  1777. END SetDocumentParms;
  1778.  
  1779. PROCEDURE SetScrollParms (wdw : INTEGER; pgW, pgH, minScrW, minScrH : LONGINT);
  1780. (* Setzt die Parameter fr das Bl„ttern im Dokument 
  1781.  *)
  1782.   VAR wdwPtr : ptrWdwSlot;
  1783. BEGIN
  1784.   wdwPtr := FindWindow (wdw);
  1785.   IF wdwPtr # NIL
  1786.   THEN
  1787.     WITH wdwPtr^ DO
  1788.       pageW := pgW; 
  1789.       pageH := pgH;
  1790.       minScrollW := minScrW;
  1791.       minScrollH := minScrH;
  1792.     END;
  1793.   END;
  1794. END SetScrollParms;
  1795.  
  1796. PROCEDURE GetScrollParms (wdw : INTEGER; VAR pgW, pgH, minScrW, minScrH : LONGINT);
  1797. (* Erfragt die Parameter fr das Bl„ttern im Dokument 
  1798.  *)
  1799.   VAR wdwPtr : ptrWdwSlot;
  1800. BEGIN
  1801.   wdwPtr := FindWindow (wdw);
  1802.   IF wdwPtr # NIL
  1803.   THEN
  1804.     WITH wdwPtr^ DO
  1805.       pgW := pageW;
  1806.       pgH := pageH;
  1807.       minScrW := minScrollW;
  1808.       minScrH := minScrollH;
  1809.     END;
  1810.   END;
  1811. END GetScrollParms;
  1812.  
  1813. PROCEDURE checkDocument (VAR document: LongRect);
  1814. BEGIN
  1815.   WITH document DO
  1816.     IF w < 0 THEN w := 0 END;
  1817.     IF h < 0 THEN h := 0 END;
  1818.     IF x > w THEN x := w END;
  1819.     IF y > h THEN y := h END;
  1820.   END;
  1821. END checkDocument;
  1822.  
  1823. PROCEDURE SetNewDocument (wdw : INTEGER; doc : LongRect; redraw: BOOLEAN);
  1824. (* Setzt die aktuellen Dokument-Parameter ohne automatisches Scrollen
  1825.  * Wenn redraw = TRUE, wird ein Redraw ber das komplette Fenster ausgel”st.
  1826.  *)
  1827.   VAR wdwPtr : ptrWdwSlot;
  1828.       frame  : Rectangle;
  1829. BEGIN
  1830.   wdwPtr := FindWindow (wdw);
  1831.   IF wdwPtr # NIL
  1832.   THEN
  1833.     WITH wdwPtr^ DO
  1834.       IF isIcon OR isHidden THEN RETURN END;
  1835.       document := doc;
  1836.       (* Jetzt noch Check auf Gltigkeit *)
  1837.       checkDocument (document);
  1838.       CalcVSlider (wdwPtr);
  1839.       CalcHSlider (wdwPtr);
  1840.       IF redraw THEN
  1841.         (* Workbereich berechnen, da in wdwWork nur der 
  1842.          * Scrollbereich steht *)
  1843.         MagicAES.WindCalc (MagicAES.WCWORK, comps, wdwCurr, frame);
  1844.         updateWdw (wdwPtr, frame);
  1845.       END;
  1846.     END;
  1847.   END;
  1848. END SetNewDocument;
  1849.  
  1850. PROCEDURE SetWdwDocument (wdw : INTEGER; doc : LongRect);
  1851. (* Setzt die aktuellen Dokument-Parameter
  1852.  *)
  1853.   VAR wdwPtr : ptrWdwSlot;
  1854.       oldDoc : LongRect;
  1855.       fullRedraw : BOOLEAN;
  1856. BEGIN
  1857.   wdwPtr := FindWindow (wdw);
  1858.   IF wdwPtr # NIL
  1859.   THEN
  1860.     WITH wdwPtr^ DO
  1861.       IF isIcon OR isHidden THEN RETURN END;
  1862.       oldDoc := document;
  1863.       document := doc;
  1864.       (* Jetzt noch Check auf Gltigkeit *)
  1865.       checkDocument (document);
  1866.       fullRedraw := FALSE;
  1867.       (* Jetzt Fenster ggf. scrollen *)
  1868.       IF doc.x # oldDoc.x THEN
  1869.         (* evtl. horizontales scrollen *)
  1870.         IF (doc.x > oldDoc.x) & ~fullRedraw THEN
  1871.           (* Nach links scrollen *)
  1872.           IF (doc.x - oldDoc.x) * xFactor < LONG(wdwWork.w)
  1873.           THEN 
  1874.             (* Scrollen lohnt sich *)
  1875.             scrollLR (wdwPtr, RIGHT, SHORT((doc.x - oldDoc.x)*xFactor));
  1876.           ELSE
  1877.             fullRedraw := TRUE;
  1878.           END;
  1879.         ELSIF ~fullRedraw
  1880.         THEN
  1881.           IF (oldDoc.x - doc.x) * xFactor < LONG(wdwWork.w)
  1882.           THEN
  1883.             (* Scrollen lohnt sich *)
  1884.             scrollLR (wdwPtr, LEFT, SHORT((oldDoc.x - doc.x)*xFactor));
  1885.           ELSE
  1886.             fullRedraw := TRUE;
  1887.           END;
  1888.         END;
  1889.       END;
  1890.       IF doc.y # oldDoc.y THEN
  1891.         (* evtl. vertikales scrollen *)
  1892.         IF ~fullRedraw & (doc.y > oldDoc.y) THEN
  1893.           (* Nach oben scrollen *)
  1894.           IF (doc.y - oldDoc.y) * yFactor < LONG(wdwWork.h)
  1895.           THEN 
  1896.             (* Scrollen lohnt sich *)
  1897.             scrollWdw (wdwPtr, DOWN, SHORT((doc.y - oldDoc.y)*yFactor));
  1898.           ELSE
  1899.             fullRedraw := TRUE;
  1900.           END;
  1901.         ELSIF ~fullRedraw
  1902.         THEN
  1903.           IF (oldDoc.y - doc.y) * yFactor < LONG(wdwWork.h)
  1904.           THEN
  1905.             (* Scrollen lohnt sich *)
  1906.             scrollWdw (wdwPtr, UP, SHORT((oldDoc.y - doc.y)*yFactor));
  1907.           ELSE
  1908.             fullRedraw := TRUE;
  1909.           END;
  1910.         END;
  1911.       END;
  1912.       IF fullRedraw
  1913.       THEN
  1914.         updateWdw (wdwPtr, wdwWork);
  1915.       END;
  1916.       IF (doc.y # oldDoc.y) OR (doc.h # oldDoc.h)
  1917.       THEN
  1918.         CalcVSlider (wdwPtr);
  1919.       END;
  1920.       IF (doc.x # oldDoc.x) OR (doc.w # oldDoc.w)
  1921.       THEN
  1922.         CalcHSlider (wdwPtr);
  1923.       END;
  1924.     END;
  1925.   END;
  1926. END SetWdwDocument;
  1927.  
  1928. PROCEDURE GetWdwDocument (wdw : INTEGER; VAR doc : LongRect);
  1929. (* Erfragt die aktuellen Dokument-Parameter
  1930.  *)
  1931.   VAR wdwPtr : ptrWdwSlot;
  1932. BEGIN
  1933.   wdwPtr := FindWindow (wdw);
  1934.   IF wdwPtr # NIL
  1935.   THEN
  1936.     doc := wdwPtr^.document;
  1937.   END;
  1938. END GetWdwDocument;
  1939.  
  1940. PROCEDURE RedrawWdw (wdw : INTEGER; frame : Rectangle);
  1941. (* Zeichnet das Fenster im Bereich Frame neu, beachtet
  1942.  * Rechteckliste und ruft indirekt die drawProc auf
  1943.  *)
  1944.   VAR wdwPtr : ptrWdwSlot;
  1945. BEGIN
  1946.   wdwPtr := FindWindow (wdw);
  1947.   IF wdwPtr # NIL
  1948.   THEN
  1949.     updateWdw (wdwPtr, frame);
  1950.   END;
  1951. END RedrawWdw;
  1952.  
  1953. PROCEDURE FullRedrawWdw (wdw : INTEGER);
  1954. (* Zeichnet das Fenster im Bereich Frame neu, beachtet
  1955.  * Rechteckliste und ruft indirekt die drawProc auf
  1956.  *)
  1957.   VAR wdwPtr : ptrWdwSlot;
  1958.       r      : Rectangle;
  1959. BEGIN
  1960.   wdwPtr := FindWindow (wdw);
  1961.   IF wdwPtr # NIL
  1962.   THEN
  1963.     MagicAES.WindGet (wdw, MagicAES.WFWORKXYWH, r);
  1964.     updateWdw (wdwPtr, r);
  1965.   END;
  1966. END FullRedrawWdw;
  1967.  
  1968. PROCEDURE SetWdwInfoline (wdw : INTEGER; info : ARRAY OF CHAR);
  1969.   VAR wdwPtr : ptrWdwSlot;
  1970.       adr    : RECORD a,b : ADDRESS END;
  1971.       voidO  : BOOLEAN;
  1972. BEGIN
  1973.   wdwPtr := FindWindow (wdw);
  1974.   IF wdwPtr # NIL
  1975.   THEN
  1976.     WITH wdwPtr^ DO
  1977.       Strings.Assign (info, wdwInfo, voidO);
  1978.       IF MagicAES.INFO IN comps
  1979.       THEN
  1980.         (* Infozeile *)
  1981.         adr.a := ADR(wdwInfo);
  1982.         MagicAES.WindSet(wdw, MagicAES.WFINFO, adr);
  1983.       END;
  1984.     END;
  1985.   END;
  1986. END SetWdwInfoline;
  1987.  
  1988. PROCEDURE SetWdwTitle (wdw : INTEGER; title : ARRAY OF CHAR);
  1989.   VAR wdwPtr : ptrWdwSlot;
  1990.       adr    : RECORD a,b : ADDRESS END;
  1991.       voidO  : BOOLEAN;
  1992. BEGIN
  1993.   wdwPtr := FindWindow (wdw);
  1994.   IF wdwPtr # NIL
  1995.   THEN
  1996.     WITH wdwPtr^ DO
  1997.       Strings.Assign (title, wdwTitle, voidO);
  1998.       IF LENGTH (wdwTitle) > 0
  1999.       THEN
  2000.         (* Jetzt ggf. ein Space vorne und hinten anfgen *)
  2001.         IF wdwTitle[0] # ' '
  2002.         THEN
  2003.           Strings.Insert (' ', 0, wdwTitle, voidO);
  2004.         END;
  2005.         IF wdwTitle[LENGTH(wdwTitle)-1] # ' '
  2006.         THEN
  2007.           Strings.Append (' ', wdwTitle, voidO);
  2008.         END;
  2009.       END;
  2010.       IF MagicAES.NAME IN comps
  2011.       THEN
  2012.         (* Titelzeile *)
  2013.         adr.a := ADR(wdwTitle);
  2014.         MagicAES.WindSet(wdw, MagicAES.WFNAME, adr);
  2015.       END;
  2016.     END;
  2017.   END;
  2018. END SetWdwTitle;
  2019.  
  2020. PROCEDURE OpenWindow (button : handleButtonProc; key  : handleKeyProc; timer : handleTimerProc;
  2021.                       fullSize : Rectangle; VAR currSize : Rectangle; wdwParts : BITSET; 
  2022.                       wdwSnap : BOOLEAN; REF info, titel : ARRAY OF CHAR;
  2023.                       snapP : snapProc; close : closeProc; draw : drawProc; top : topProc;
  2024.                       untop : untopProc; update : updateProc; setWdw : setWorkProc; 
  2025.                       getScroll : getRectProc; hide : hideProc;
  2026.                       pixelOffset : INTEGER; env : ADDRESS;
  2027.                       onlyThisTop : BOOLEAN; showIt : BOOLEAN; 
  2028.                       supportIconify : BOOLEAN; openWorkstation: BOOLEAN;
  2029.                       VAR wdwHandle, vdiHandle : INTEGER): BOOLEAN;
  2030. (* ™ffnet Fenster und Workstation, setzt Font und Size, 
  2031.  * alle Prozeduren setzen 
  2032.  *)
  2033.  VAR wdwPtr : ptrWdwSlot;
  2034.      work   : Rectangle;
  2035.      adr    : RECORD a,b : ADDRESS END;
  2036.      oldTop : ptrWdwSlot;
  2037.      bits   : INTEGER;
  2038.      voidO  : BOOLEAN;
  2039. BEGIN
  2040.   (*
  2041.   IF onlyThisTop & (onlyOneTop >= 0)
  2042.   THEN
  2043.     wdwHandle := -1;
  2044.     vdiHandle := -1;
  2045.     RETURN FALSE
  2046.   END;
  2047.   *)
  2048.   (* Neuen WindowPtr einrichten, Window erzeugen und ”ffnen, Workstation ”ffnen *)
  2049.   NEW (wdwPtr);
  2050.   IF wdwPtr = NIL
  2051.   THEN 
  2052.     RETURN FALSE
  2053.   END;
  2054.   IF iconifySupportEnabled & supportIconify
  2055.   THEN
  2056.     IF (MagicAES.ApplGetinfo (MagicAES.AEWINDOWS, v.int, v.int, bits, v.int) = 1)
  2057.     THEN
  2058.       IF MagicSys.Bit0 IN BITSET(bits)
  2059.       THEN
  2060.         (* Iconify-Gadget einfgen *)
  2061.         INCL (wdwParts, MagicAES.SMALLER);
  2062.       END;
  2063.       (*
  2064.       IF MagicSys.Bit3 IN BITSET(bits)
  2065.       THEN
  2066.         (* HotClose-Box einfgen (wasauchimmer das sein mag) *)
  2067.         INCL (wdwParts, MagicAES.HOTCLOSEBOX);
  2068.       END;
  2069.       *)
  2070.     END;
  2071.   END;
  2072.   IF magIx
  2073.   THEN
  2074.     IF (MagicAES.NAME IN wdwParts) OR (MagicAES.MOVE IN wdwParts)
  2075.     THEN
  2076.       (* Backdrop hinzufgen, damit wir die Message bekommen! *)
  2077.       INCL (wdwParts, MagicAES.BACKDROP);
  2078.     END;
  2079.   END;
  2080.   wdwHandle := MagicAES.WindCreate (wdwParts, fullSize);
  2081.   IF wdwHandle < 0
  2082.   THEN
  2083.     (* Kein Fenster mehr frei *)
  2084.     DISPOSE (wdwPtr);
  2085.     RETURN FALSE;
  2086.   END;
  2087.   IF openWorkstation
  2088.   THEN
  2089.     vdiHandle := mtAppl.OpenWorkstation (mtAppl.Screen, 0, 0, TRUE);
  2090.     IF vdiHandle < 0 THEN
  2091.       DISPOSE (wdwPtr);
  2092.       MagicAES.WindDelete (wdwHandle);
  2093.       RETURN FALSE
  2094.     END;
  2095.   ELSE
  2096.     vdiHandle := -1
  2097.   END;
  2098.   (* So, jetzt noch in Liste einh„ngen *)
  2099.   wdwPtr^.prev := NIL;
  2100.   IF windows = NIL
  2101.   THEN
  2102.     wdwPtr^.next := NIL;
  2103.   ELSE
  2104.     (* Am Anfang einh„ngen *)
  2105.     wdwPtr^.next := windows;
  2106.     windows^.prev := wdwPtr;
  2107.   END;
  2108.   windows := wdwPtr;
  2109.   (* Ok, alles da! *)
  2110.   WITH wdwPtr^ DO
  2111.     wdw := wdwHandle;
  2112.     vdi := vdiHandle;
  2113.     used := TRUE;
  2114.     isTop := TRUE;
  2115.     isFull := FALSE;
  2116.     comps := wdwParts;
  2117.     snap    := wdwSnap;
  2118.     wdwFull := fullSize;
  2119.     pixOff  := pixelOffset;
  2120.     wdwMenu := NIL;
  2121.     wdwDial := NIL;
  2122.     onlyTop := onlyThisTop;
  2123.     lastOnlyTop := onlyOneTop;
  2124.     IF onlyThisTop
  2125.     THEN
  2126.       onlyOneTop := wdwHandle;
  2127.     END;
  2128.     (* Event-Handler installieren *)
  2129.     hdlButton := button;
  2130.     hdlKey := key;
  2131.     hdlTimer := timer;
  2132.     (* Slidergr”žen initialisieren *)
  2133.     VslSize := -1;
  2134.     VslPos  := -1;
  2135.     HslSize := -1;
  2136.     HslPos  := -1;
  2137.     (* Request-Handler installieren *)
  2138.     hdlSnap   := snapP;
  2139.     hdlClose  := close;
  2140.     hdlDraw   := draw;
  2141.     hdlTop    := top;
  2142.     hdlUntop  := untop;
  2143.     hdlUpdate := update;
  2144.     setNewWdw := setWdw;
  2145.     wdwGetScroll := getScroll;
  2146.     hdlHide   := hide;
  2147.     hdlRect   := handleRectProc(NIL);
  2148.     special   := env;
  2149.     ddClientInstalled := FALSE;
  2150.     ddServerInstalled := FALSE;
  2151.     WITH currSize DO
  2152.       w := BinOps.HigherInt (w, minWindWidth);
  2153.       h := BinOps.HigherInt (h, minWindHeight);
  2154.     END;
  2155.     wdwCurr := currSize;
  2156.     (* Dokument-Variablen setzen *)
  2157.     document := LongRect {0, 0, 0, 0};
  2158.     pageW := 0;
  2159.     pageH := 0;
  2160.     yFactor := 1;
  2161.     xFactor := 1;
  2162.     minScrollW := 1;
  2163.     minScrollH := 1;
  2164.     (* Titel und Infozeile setzen *)
  2165.     Strings.Assign (titel, wdwTitle, v.bool);
  2166.     Strings.Assign (info, wdwInfo, v.bool);
  2167.     IF MagicAES.INFO IN comps
  2168.     THEN
  2169.       (* Infozeile *)
  2170.       adr.a := ADR(wdwInfo);
  2171.       MagicAES.WindSet(wdw, MagicAES.WFINFO, adr);
  2172.     END;
  2173.     IF MagicAES.NAME IN comps
  2174.     THEN
  2175.       (* Jetzt ggf. ein Space vorne und hinten anfgen *)
  2176.       IF LENGTH (wdwTitle) > 0
  2177.       THEN
  2178.         IF wdwTitle[0] # ' '
  2179.         THEN
  2180.           Strings.Insert (' ', 0, wdwTitle, voidO);
  2181.         END;
  2182.         IF wdwTitle[LENGTH(wdwTitle)-1] # ' '
  2183.         THEN
  2184.           Strings.Append (' ', wdwTitle, voidO);
  2185.         END;
  2186.       END;
  2187.       (* Titelzeile *)
  2188.       adr.a := ADR(wdwTitle);
  2189.       MagicAES.WindSet(wdw, MagicAES.WFNAME, adr);
  2190.     END;
  2191.     (* Jetzt Fenster ”ffnen *)
  2192.     MagicAES.WindCalc (MagicAES.WCWORK, comps, currSize, wdwWork);
  2193.     (* Jetzt snappen *)
  2194.     IF snap THEN hdlSnap (wdw, vdi, special, wdwWork); END;
  2195.     (* Scrollrechteck holen *)
  2196.     MagicAES.WindCalc (MagicAES.WCBORDER, comps, wdwWork, wdwCurr);
  2197.     wdwGetScroll (wdw, vdi, special, wdwWork);
  2198.     IF showIt THEN
  2199.       (* Altes TopWindow untoppen *)
  2200.       oldTop := FindTop();
  2201.       IF oldTop # NIL THEN
  2202.         untopWdw (oldTop);
  2203.       END;
  2204.       MagicAES.WindOpen (wdw, wdwCurr);
  2205.       v.bool := hdlTop (wdw, vdi, special);
  2206.     END;
  2207.     isHidden := ~showIt;
  2208.     isIcon := FALSE;
  2209.   END; (* WITH wdwPtr *)
  2210.   IF showIt
  2211.   THEN
  2212.     (* Noch merken, das dieses jetzt top ist *)
  2213.     NewWindowIsTop (wdwHandle, mtAppl.ApplIdent);
  2214.   END;
  2215.   (* fettisch! *)
  2216.   RETURN TRUE
  2217. END OpenWindow;
  2218.  
  2219. PROCEDURE CreateWindow (fullSize : Rectangle; VAR currSize : Rectangle; 
  2220.                         wdwParts : BITSET; REF info, titel : ARRAY OF CHAR;
  2221.                         env : ADDRESS; supportIconify: BOOLEAN;
  2222.                         openWorkstation: BOOLEAN;
  2223.                         VAR wdwHandle, vdiHandle : INTEGER): BOOLEAN;
  2224. (* Erzeugt ein Fenster, das mit Default-Prozeduren behandelt wird. 
  2225.  * Weitere Einstellungen muž man danach vornehmen 
  2226.  *)
  2227.  VAR wdwPtr : ptrWdwSlot;
  2228.      work   : Rectangle;
  2229.      adr    : RECORD a,b : ADDRESS END;
  2230.      oldTop : ptrWdwSlot;
  2231.      bits   : INTEGER;
  2232.      voidO  : BOOLEAN;
  2233. BEGIN
  2234.   (* Neuen WindowPtr einrichten, Window erzeugen und ”ffnen, Workstation ”ffnen *)
  2235.   NEW (wdwPtr);
  2236.   IF wdwPtr = NIL
  2237.   THEN 
  2238.     RETURN FALSE
  2239.   END;
  2240.   IF iconifySupportEnabled & supportIconify
  2241.   THEN
  2242.     IF (MagicAES.ApplGetinfo (MagicAES.AEWINDOWS, v.int, v.int, bits, v.int) = 1)
  2243.      & (MagicSys.Bit0 IN BITSET(bits))
  2244.     THEN
  2245.       (* Iconify-Gadget einfgen *)
  2246.       INCL (wdwParts, MagicAES.SMALLER);
  2247.     END;
  2248.   END;
  2249.   wdwHandle := MagicAES.WindCreate (wdwParts, fullSize);
  2250.   IF wdwHandle < 0
  2251.   THEN
  2252.     (* Kein Fenster mehr frei *)
  2253.     DISPOSE (wdwPtr);
  2254.     RETURN FALSE;
  2255.   END;
  2256.   IF openWorkstation
  2257.   THEN
  2258.     vdiHandle := mtAppl.OpenWorkstation (mtAppl.Screen, 0, 0, TRUE);
  2259.     IF vdiHandle < 0 THEN
  2260.       DISPOSE (wdwPtr);
  2261.       MagicAES.WindDelete (wdwHandle);
  2262.       RETURN FALSE
  2263.     END;
  2264.   ELSE
  2265.     vdiHandle := -1
  2266.   END;
  2267.   (* So, jetzt noch in Liste einh„ngen *)
  2268.   wdwPtr^.prev := NIL;
  2269.   IF windows = NIL
  2270.   THEN
  2271.     wdwPtr^.next := NIL;
  2272.   ELSE
  2273.     (* Am Anfang einh„ngen *)
  2274.     wdwPtr^.next := windows;
  2275.     windows^.prev := wdwPtr;
  2276.   END;
  2277.   windows := wdwPtr;
  2278.   (* Ok, alles da! *)
  2279.   WITH wdwPtr^ DO
  2280.     wdw := wdwHandle;
  2281.     vdi := vdiHandle;
  2282.     used := TRUE;
  2283.     isTop := FALSE;
  2284.     isFull := FALSE;
  2285.     comps := wdwParts;
  2286.     snap    := FALSE;
  2287.     wdwFull := fullSize;
  2288.     pixOff  := 0;
  2289.     wdwMenu := NIL;
  2290.     wdwDial := NIL;
  2291.     onlyTop := FALSE;
  2292.     (* Default Event-Handler installieren *)
  2293.     hdlButton := defButton;
  2294.     hdlKey := defKey;
  2295.     hdlTimer := defTimer;
  2296.     (* Slidergr”žen initialisieren *)
  2297.     VslSize := -1;
  2298.     VslPos  := -1;
  2299.     HslSize := -1;
  2300.     HslPos  := -1;
  2301.     (* Default Request-Handler installieren *)
  2302.     hdlSnap   := defSnap;
  2303.     hdlClose  := defClose;
  2304.     hdlDraw   := defDraw;
  2305.     hdlTop    := defTop;
  2306.     hdlUntop  := defUntop;
  2307.     hdlUpdate := defUpdate;
  2308.     setNewWdw := defSetwork;
  2309.     wdwGetScroll := defGetrect;
  2310.     hdlHide   := defHide;
  2311.     hdlRect   := handleRectProc(NIL);
  2312.     special   := env;
  2313.     ddClientInstalled := FALSE;
  2314.     ddServerInstalled := FALSE;
  2315.     WITH currSize DO
  2316.       w := BinOps.HigherInt (w, minWindWidth);
  2317.       h := BinOps.HigherInt (h, minWindHeight);
  2318.     END;
  2319.     wdwCurr := currSize;
  2320.     (* Dokument-Variablen setzen *)
  2321.     document := LongRect {0, 0, 0, 0};
  2322.     pageW := 0;
  2323.     pageH := 0;
  2324.     yFactor := 1;
  2325.     xFactor := 1;
  2326.     minScrollW := 1;
  2327.     minScrollH := 1;
  2328.     (* Titel und Infozeile setzen *)
  2329.     Strings.Assign (titel, wdwTitle, v.bool);
  2330.     Strings.Assign (info, wdwInfo, v.bool);
  2331.     IF MagicAES.INFO IN comps
  2332.     THEN
  2333.       (* Infozeile *)
  2334.       adr.a := ADR(wdwInfo);
  2335.       MagicAES.WindSet(wdw, MagicAES.WFINFO, adr);
  2336.     END;
  2337.     IF MagicAES.NAME IN comps
  2338.     THEN
  2339.       (* Jetzt ggf. ein Space vorne und hinten anfgen *)
  2340.       IF LENGTH (wdwTitle) > 0
  2341.       THEN
  2342.         IF wdwTitle[0] # ' '
  2343.         THEN
  2344.           Strings.Insert (' ', 0, wdwTitle, voidO);
  2345.         END;
  2346.         IF wdwTitle[LENGTH(wdwTitle)-1] # ' '
  2347.         THEN
  2348.           Strings.Append (' ', wdwTitle, voidO);
  2349.         END;
  2350.       END;
  2351.       (* Titelzeile *)
  2352.       adr.a := ADR(wdwTitle);
  2353.       MagicAES.WindSet(wdw, MagicAES.WFNAME, adr);
  2354.     END;
  2355.     (* Jetzt Fenster ”ffnen *)
  2356.     MagicAES.WindCalc (MagicAES.WCWORK, comps, currSize, wdwWork);
  2357.     (* Jetzt snappen *)
  2358.     IF snap THEN hdlSnap (wdw, vdi, special, wdwWork); END;
  2359.     (* Scrollrechteck holen *)
  2360.     MagicAES.WindCalc (MagicAES.WCBORDER, comps, wdwWork, wdwCurr);
  2361.     wdwGetScroll (wdw, vdi, special, wdwWork);
  2362.     isHidden := TRUE;
  2363.     isIcon := FALSE;
  2364.   END; (* WITH wdwPtr *)
  2365.   (* fettisch! *)
  2366.   RETURN TRUE
  2367. END CreateWindow;
  2368.  
  2369. PROCEDURE SetWindowDraw (wdw: INTEGER; draw: drawProc): BOOLEAN;
  2370. (* Setzt die Zeichenprozedur fr ein Fenster. False: Fenster nicht gefunden
  2371.  *)
  2372.  VAR wdwPtr : ptrWdwSlot;
  2373. BEGIN
  2374.   wdwPtr := FindWindow (wdw);
  2375.   IF (wdwPtr # NIL)
  2376.   THEN
  2377.     wdwPtr^.hdlDraw := draw;
  2378.   END;
  2379.   RETURN wdwPtr # NIL
  2380. END SetWindowDraw;
  2381.  
  2382. PROCEDURE SetWindowSnap (wdw: INTEGER; snap: snapProc): BOOLEAN;
  2383. (* Setzt die Snapprozedur fr ein Fenster. Diese wird dann
  2384.  * bei jedem Sizen und einmal direkt mit den aktuellen Werten
  2385.  * aufgerufen. False: Fenster nicht gefunden
  2386.  *)
  2387.  VAR wdwPtr : ptrWdwSlot;
  2388. BEGIN
  2389.   wdwPtr := FindWindow (wdw);
  2390.   IF (wdwPtr # NIL)
  2391.   THEN
  2392.     wdwPtr^.hdlSnap := snap;
  2393.     wdwPtr^.snap := TRUE;
  2394.   END;
  2395.   RETURN wdwPtr # NIL
  2396. END SetWindowSnap;
  2397.  
  2398. PROCEDURE SetWindowButton (wdw: INTEGER; button: handleButtonProc): BOOLEAN;
  2399. (* Setzt den Buttonhandler fr ein Fenster. False: Fenster nicht gefunden
  2400.  *)
  2401.  VAR wdwPtr : ptrWdwSlot;
  2402. BEGIN
  2403.   wdwPtr := FindWindow (wdw);
  2404.   IF (wdwPtr # NIL)
  2405.   THEN
  2406.     wdwPtr^.hdlButton := button;
  2407.   END;
  2408.   RETURN wdwPtr # NIL
  2409. END SetWindowButton;
  2410.  
  2411. PROCEDURE SetWindowKey (wdw: INTEGER; key: handleKeyProc): BOOLEAN;
  2412. (* Setzt den Keyhandler fr ein Fenster. False: Fenster nicht gefunden
  2413.  *)
  2414.  VAR wdwPtr : ptrWdwSlot;
  2415. BEGIN
  2416.   wdwPtr := FindWindow (wdw);
  2417.   IF (wdwPtr # NIL)
  2418.   THEN
  2419.     wdwPtr^.hdlKey := key;
  2420.   END;
  2421.   RETURN wdwPtr # NIL
  2422. END SetWindowKey;
  2423.  
  2424. PROCEDURE SetWindowTimer (wdw: INTEGER; timer: handleTimerProc): BOOLEAN;
  2425. (* Setzt den Timerhandler fr ein Fenster. False: Fenster nicht gefunden
  2426.  *)
  2427.  VAR wdwPtr : ptrWdwSlot;
  2428. BEGIN
  2429.   wdwPtr := FindWindow (wdw);
  2430.   IF (wdwPtr # NIL)
  2431.   THEN
  2432.     wdwPtr^.hdlTimer := timer;
  2433.   END;
  2434.   RETURN wdwPtr # NIL
  2435. END SetWindowTimer;
  2436.  
  2437. PROCEDURE SetWindowRectProc (wdw: INTEGER; rect: handleRectProc): BOOLEAN;
  2438. (* Setzt den Rechteckhandler fr ein Fenster. False: Fenster nicht gefunden
  2439.  *)
  2440.  VAR wdwPtr : ptrWdwSlot;
  2441. BEGIN
  2442.   wdwPtr := FindWindow (wdw);
  2443.   IF (wdwPtr # NIL)
  2444.   THEN
  2445.     wdwPtr^.hdlRect := rect;
  2446.   END;
  2447.   RETURN wdwPtr # NIL
  2448. END SetWindowRectProc;
  2449.  
  2450. PROCEDURE SetWindowClose (wdw: INTEGER; close: closeProc): BOOLEAN;
  2451. (* Setzt den Closehandler fr ein Fenster. False: Fenster nicht gefunden
  2452.  *)
  2453.  VAR wdwPtr : ptrWdwSlot;
  2454. BEGIN
  2455.   wdwPtr := FindWindow (wdw);
  2456.   IF (wdwPtr # NIL)
  2457.   THEN
  2458.     wdwPtr^.hdlClose := close;
  2459.   END;
  2460.   RETURN wdwPtr # NIL
  2461. END SetWindowClose;
  2462.  
  2463. PROCEDURE SetWindowTop (wdw: INTEGER; top: topProc): BOOLEAN;
  2464. (* Setzt den Tophandler fr ein Fenster. False: Fenster nicht gefunden
  2465.  *)
  2466.  VAR wdwPtr : ptrWdwSlot;
  2467. BEGIN
  2468.   wdwPtr := FindWindow (wdw);
  2469.   IF (wdwPtr # NIL)
  2470.   THEN
  2471.     wdwPtr^.hdlTop := top;
  2472.   END;
  2473.   RETURN wdwPtr # NIL
  2474. END SetWindowTop;
  2475.  
  2476. PROCEDURE SetWindowUntop (wdw: INTEGER; untop: untopProc): BOOLEAN;
  2477. (* Setzt den Untophandler fr ein Fenster. False: Fenster nicht gefunden
  2478.  *)
  2479.  VAR wdwPtr : ptrWdwSlot;
  2480. BEGIN
  2481.   wdwPtr := FindWindow (wdw);
  2482.   IF (wdwPtr # NIL)
  2483.   THEN
  2484.     wdwPtr^.hdlUntop := untop;
  2485.   END;
  2486.   RETURN wdwPtr # NIL
  2487. END SetWindowUntop;
  2488.  
  2489. PROCEDURE SetWindowUpdate (wdw: INTEGER; update: updateProc): BOOLEAN;
  2490. (* Setzt den Updatehandler fr ein Fenster. False: Fenster nicht gefunden
  2491.  *)
  2492.  VAR wdwPtr : ptrWdwSlot;
  2493. BEGIN
  2494.   wdwPtr := FindWindow (wdw);
  2495.   IF (wdwPtr # NIL)
  2496.   THEN
  2497.     wdwPtr^.hdlUpdate := update;
  2498.   END;
  2499.   RETURN wdwPtr # NIL
  2500. END SetWindowUpdate;
  2501.  
  2502. PROCEDURE SetWindowSwork (wdw: INTEGER; setWdw: setWorkProc): BOOLEAN;
  2503. (* Setzt den Handler fr Dokument„nderungen im Fenster. False: Fenster nicht gefunden
  2504.  *)
  2505.  VAR wdwPtr : ptrWdwSlot;
  2506. BEGIN
  2507.   wdwPtr := FindWindow (wdw);
  2508.   IF (wdwPtr # NIL)
  2509.   THEN
  2510.     wdwPtr^.setNewWdw := setWdw;
  2511.   END;
  2512.   RETURN wdwPtr # NIL
  2513. END SetWindowSwork;
  2514.  
  2515. PROCEDURE SetWindowGetScroll (wdw: INTEGER; getScroll: getRectProc): BOOLEAN;
  2516. (* Setzt den GetScrollRect-Handler fr ein Fenster. False: Fenster nicht gefunden
  2517.  *)
  2518.  VAR wdwPtr : ptrWdwSlot;
  2519. BEGIN
  2520.   wdwPtr := FindWindow (wdw);
  2521.   IF (wdwPtr # NIL)
  2522.   THEN
  2523.     wdwPtr^.wdwGetScroll := getScroll;
  2524.   END;
  2525.   RETURN wdwPtr # NIL
  2526. END SetWindowGetScroll;
  2527.  
  2528. PROCEDURE SetWindowHide (wdw: INTEGER; hide: hideProc): BOOLEAN;
  2529. (* Setzt den Hidehandler fr ein Fenster. False: Fenster nicht gefunden
  2530.  *)
  2531.  VAR wdwPtr : ptrWdwSlot;
  2532. BEGIN
  2533.   wdwPtr := FindWindow (wdw);
  2534.   IF (wdwPtr # NIL)
  2535.   THEN
  2536.     wdwPtr^.hdlHide := hide;
  2537.   END;
  2538.   RETURN wdwPtr # NIL
  2539. END SetWindowHide;
  2540.  
  2541. PROCEDURE SetWindowPixOff (wdw: INTEGER; pixelOffset: INTEGER): BOOLEAN;
  2542. (* Setzt den linken Offset fr ein Fenster. False: Fenster nicht gefunden
  2543.  *)
  2544.  VAR wdwPtr : ptrWdwSlot;
  2545. BEGIN
  2546.   wdwPtr := FindWindow (wdw);
  2547.   IF (wdwPtr # NIL)
  2548.   THEN
  2549.     wdwPtr^.pixOff := pixelOffset;
  2550.   END;
  2551.   RETURN wdwPtr # NIL
  2552. END SetWindowPixOff;
  2553.  
  2554. PROCEDURE SetWindowMode (wdw: INTEGER; onlyThisTop: BOOLEAN): BOOLEAN;
  2555. (* Setzt den Modus fr ein Fenster. False: Fenster nicht gefunden
  2556.  *)
  2557.  VAR wdwPtr : ptrWdwSlot;
  2558. BEGIN
  2559.   (*
  2560.   IF onlyThisTop & (onlyOneTop >= 0)
  2561.   THEN
  2562.     RETURN FALSE
  2563.   END;
  2564.   *)
  2565.   wdwPtr := FindWindow (wdw);
  2566.   IF (wdwPtr # NIL)
  2567.   THEN
  2568.     wdwPtr^.onlyTop := onlyThisTop;
  2569.     IF onlyThisTop
  2570.     THEN
  2571.       wdwPtr^.lastOnlyTop := onlyOneTop;
  2572.       onlyOneTop := wdw;
  2573.     END;
  2574.   END;
  2575.   RETURN wdwPtr # NIL
  2576. END SetWindowMode;
  2577.  
  2578. PROCEDURE SetWindowDial (wdw: INTEGER; dial: ADDRESS): BOOLEAN;
  2579. (* Setzt die Dialogadresse fr das Fenster. False: Fenster nicht gefunden
  2580.  *)
  2581.  VAR wdwPtr : ptrWdwSlot;
  2582. BEGIN
  2583.   wdwPtr := FindWindow (wdw);
  2584.   IF (wdwPtr # NIL)
  2585.   THEN
  2586.     wdwPtr^.wdwDial := dial;
  2587.   END;
  2588.   RETURN wdwPtr # NIL
  2589. END SetWindowDial;
  2590.  
  2591. PROCEDURE SetWindowMenu (wdw: INTEGER; menu: ADDRESS): BOOLEAN;
  2592. (* Setzt die Menuadresse fr das Fenster. False: Fenster nicht gefunden
  2593.  *)
  2594.  VAR wdwPtr : ptrWdwSlot;
  2595. BEGIN
  2596.   wdwPtr := FindWindow (wdw);
  2597.   IF (wdwPtr # NIL)
  2598.   THEN
  2599.     wdwPtr^.wdwMenu := menu;
  2600.   END;
  2601.   RETURN wdwPtr # NIL
  2602. END SetWindowMenu;
  2603.  
  2604. PROCEDURE ShowWindow (wdw: INTEGER) : BOOLEAN;
  2605.  VAR wdwPtr : ptrWdwSlot;
  2606. BEGIN
  2607.   wdwPtr := FindWindow (wdw);
  2608.   IF (wdwPtr # NIL) & (wdwPtr^.isHidden)
  2609.   THEN
  2610.     showWdw (wdwPtr, TRUE);
  2611.     RETURN TRUE;
  2612.   ELSE
  2613.     RETURN FALSE
  2614.   END;
  2615. END ShowWindow;
  2616.  
  2617. PROCEDURE HideWindow (wdw: INTEGER) : BOOLEAN;
  2618.  VAR wdwPtr : ptrWdwSlot;
  2619. BEGIN
  2620.   wdwPtr := FindWindow (wdw);
  2621.   IF (wdwPtr # NIL) & ~(wdwPtr^.isHidden)
  2622.   THEN
  2623.     hideWdw (wdwPtr);
  2624.     RETURN TRUE;
  2625.   ELSE
  2626.     RETURN FALSE
  2627.   END;
  2628. END HideWindow;
  2629.  
  2630. PROCEDURE SendCloseWindow (wdw : INTEGER);
  2631.  VAR wdwPtr : ptrWdwSlot;
  2632.      apId   : INTEGER;
  2633. BEGIN
  2634.   wdwPtr := FindWindow (wdw);
  2635.   IF wdwPtr # NIL
  2636.   THEN
  2637.     apId := mtAppl.ApplIdent;
  2638.     SendClosed (wdw, apId);
  2639.   ELSE
  2640.     IF GetApId (wdw, apId)
  2641.     THEN 
  2642.       SendClosed (wdw, apId);
  2643.     END;
  2644.   END;
  2645. END SendCloseWindow;
  2646.  
  2647. PROCEDURE CloseWindow (wdw : INTEGER; force : BOOLEAN): BOOLEAN;
  2648. (* Schliežt Fenster und Workstation und entfernt die Handler aus der Liste 
  2649.  *)
  2650.  VAR wdwPtr : ptrWdwSlot;
  2651.      apId   : INTEGER;
  2652. BEGIN
  2653.   wdwPtr := FindWindow (wdw);
  2654.   IF wdwPtr # NIL
  2655.   THEN
  2656.     IF (onlyOneTop >= 0) & (wdwPtr^.wdw # onlyOneTop) & (~force) THEN 
  2657.       RETURN FALSE
  2658.     END;
  2659.     RETURN closeWdw (wdwPtr, force);
  2660.   ELSE
  2661.     IF GetApId (wdw, apId)
  2662.     THEN 
  2663.       SendClosed (wdw, apId);
  2664.     END;
  2665.   END;
  2666.   RETURN TRUE
  2667. END CloseWindow;
  2668.  
  2669. PROCEDURE CloseAllWindows (force : BOOLEAN): BOOLEAN;
  2670. (* Schliežt alle Fenster, die dem Modul bekannt sind. 
  2671.  * Die Fenster werden alle ber CloseWindow geschlossen,
  2672.  * und falls ein CloseWindow FALSE zurckliefert, dann
  2673.  * wird der Returnwert zurckgegeben und abgebrochen.
  2674.  *)
  2675.   VAR wdwPtr : ptrWdwSlot;
  2676. BEGIN
  2677.   wdwPtr := windows;
  2678.   WHILE wdwPtr # NIL DO
  2679.     IF ~ CloseWindow (wdwPtr^.wdw, force)
  2680.     THEN 
  2681.       RETURN FALSE
  2682.     END;
  2683.     wdwPtr := windows;
  2684.   END;
  2685.   RETURN TRUE;
  2686. END CloseAllWindows;
  2687.  
  2688. PROCEDURE FullWindow (wdw : INTEGER);
  2689. (* Tut so, als ob das Fenster eine Fulled-Nachricht erhalten h„tte.
  2690.  * Falls das Fenster nicht vom Modul verwaltet wird, aber trotzdem 
  2691.  * in der WindowQueue enthalten ist, dann wird an das Fenster
  2692.  * eine Fulled-Nachricht geschickt.
  2693.  *)
  2694.  VAR wdwPtr : ptrWdwSlot;
  2695.      apId   : INTEGER;
  2696. BEGIN
  2697.   wdwPtr := FindWindow (wdw);
  2698.   IF wdwPtr # NIL
  2699.   THEN
  2700.     fullWdw (wdwPtr);
  2701.   ELSE
  2702.     IF GetApId (wdw, apId)
  2703.     THEN 
  2704.       SendFulled (wdw, apId);
  2705.     END;
  2706.   END;
  2707. END FullWindow;
  2708.  
  2709. PROCEDURE TopWindow (wdw : INTEGER);
  2710. (* Tut so, als ob das Fenster eine Topped-Nachricht erhalten h„tte.
  2711.  * Falls das Fenster nicht vom Modul verwaltet wird, aber trotzdem 
  2712.  * in der WindowQueue enthalten ist, dann wird an das Fenster
  2713.  * eine Topped-Nachricht geschickt.
  2714.  *)
  2715.  VAR wdwPtr : ptrWdwSlot;
  2716.      apId   : INTEGER;
  2717. BEGIN
  2718.   wdwPtr := FindWindow (wdw);
  2719.   IF wdwPtr # NIL
  2720.   THEN
  2721.     topWdw (wdwPtr, TRUE);
  2722.   ELSE
  2723.     IF GetApId (wdw, apId)
  2724.     THEN 
  2725.       SendTop (wdw, apId);
  2726.     END;
  2727.   END;
  2728. END TopWindow;
  2729.  
  2730. PROCEDURE SetWindowIcon (icon : ADDRESS);
  2731. (* Setzt das Icon, das in iconifizierten Fenstern gezeichnet wird. 
  2732.  * icon ist die Adresse eines Objektbaumes 
  2733.  *)
  2734. BEGIN
  2735.   iconHdl := icon;
  2736. END SetWindowIcon;
  2737.  
  2738. PROCEDURE TranslateKey (VAR key, scan: CHAR; taste: INTEGER; kstate: BITSET);
  2739. BEGIN
  2740.   IF MagicPCKeyTrans
  2741.   THEN
  2742.     CASE taste OF 
  2743.       $6328:  (* PageUp auf PC, umgesetzt auf Num-( *)
  2744.               taste := $4838;
  2745.               scan := CHAR($48); key := CHAR($38); 
  2746.               kstate := BITSET(2);
  2747.     | $6429:  (* PageDown auf PC, umgesetzt auf Num-) *)
  2748.               taste := $5032;
  2749.               scan := CHAR($50); key := CHAR($32); 
  2750.               kstate := BITSET(2);      
  2751.     | $4F00:  (* End auf Mac *)
  2752.               taste := $4737;
  2753.               scan := CHAR($47); key := CHAR($37); 
  2754.               kstate := BITSET(2);
  2755.     ELSE
  2756.     END;
  2757.   ELSE
  2758.     CASE taste OF 
  2759.       $4900:  (* PageUp auf Mac *) 
  2760.               taste := $4838;
  2761.               scan := CHAR($48); key := CHAR($38); 
  2762.               kstate := BITSET(2);
  2763.     | $5100:  (* PageDown auf Mac *)
  2764.               taste := $5032;
  2765.               scan := CHAR($50); key := CHAR($32); 
  2766.               kstate := BITSET(2);
  2767.     | $4F00:  (* End auf Mac *)
  2768.               taste := $4737;
  2769.               scan := CHAR($47); key := CHAR($37); 
  2770.               kstate := BITSET(2);
  2771.     ELSE
  2772.     END;
  2773.   END;
  2774. END TranslateKey;
  2775.  
  2776. PROCEDURE HandleEvent ( VAR event : BITSET; VAR pbuff : ARRAY OF LOC; buts, kstate : BITSET; 
  2777.                         key, scan : CHAR; taste, mx, my, clicks : INTEGER) : BOOLEAN;
  2778. (* Verteilt die events, falls n”tig. Wenn behandelt, wird TRUE zurckgegeben,
  2779.  * andernfalls FALSE
  2780.  *)
  2781.  
  2782.  VAR wdwPtr : ptrWdwSlot;
  2783.      r      : Rectangle;
  2784.      eventDone : BOOLEAN;
  2785.      evtDone: BOOLEAN;
  2786. BEGIN
  2787.   eventDone := FALSE;
  2788.   MagicAES.WindGet (0, MagicAES.WFTOP, r);
  2789.   theTopWindow := r.x;
  2790.   GetOwnTopWindow (ownTopWindow);
  2791.   IF (theTopWindow # ownTopWindow) & (FindWindow (theTopWindow) # NIL)
  2792.   THEN
  2793.     NewWindowIsTop (theTopWindow, mtAppl.ApplIdent);
  2794.     ownTopWindow := theTopWindow;
  2795.   END;
  2796.   (* Tastendrcke, gehen an Dialog oder an Fenster, wenn mit Shift *)
  2797.   IF MagicAES.MUKEYBD IN event 
  2798.   THEN
  2799.     TranslateKey (key, scan, taste, kstate);
  2800.     wdwPtr := FindWindow (ownTopWindow);
  2801.     IF wdwPtr # NIL
  2802.     THEN
  2803.       IF (onlyOneTop >= 0) OR
  2804.          (wdwPtr^.wdwDial # NIL) OR
  2805.          (MagicAES.KLSHIFT IN kstate) OR (MagicAES.KRSHIFT IN kstate)
  2806.       THEN
  2807.         WITH wdwPtr^ DO
  2808.           IF ~isIcon & ~isHidden & (hdlKey # handleKeyProc(NIL)) & hdlKey (wdw, vdi, special, taste, key, scan, kstate)
  2809.           THEN 
  2810.             EXCL (event, MagicAES.MUKEYBD);
  2811.             eventDone := TRUE;
  2812.           END;
  2813.         END;
  2814.       END 
  2815.     END;
  2816.   END;
  2817.   (* Jetzt Tastendrcke ohne Shift, gehen an globale Prozedur *)
  2818.   IF  (MagicAES.MUKEYBD IN event)        (* nicht vom Fenster behandelt *)
  2819.     & (handleGlobalKey # handleGlobalKeyProc (NIL))
  2820.   THEN
  2821.     IF handleGlobalKey ( taste, key, scan, kstate)
  2822.     THEN
  2823.       EXCL (event, MagicAES.MUKEYBD);
  2824.       eventDone := TRUE;
  2825.     END;
  2826.   END;
  2827.   (* Jetzt Tastendrcke ohne Shift, die noch brig sind *)
  2828.   IF MagicAES.MUKEYBD IN event 
  2829.   THEN
  2830.     wdwPtr := FindWindow (ownTopWindow);
  2831.     IF wdwPtr # NIL
  2832.     THEN WITH wdwPtr^ DO
  2833.       IF ~isIcon & ~isHidden & (hdlKey # handleKeyProc(NIL)) & hdlKey (wdw, vdi, special, taste, key, scan, kstate)
  2834.       THEN 
  2835.         EXCL (event, MagicAES.MUKEYBD);
  2836.         eventDone := TRUE;
  2837.       END;
  2838.     END END;
  2839.   END;
  2840.   (* Jetzt Rechteckevents *)
  2841.   IF MagicAES.MUM1 IN event
  2842.   THEN
  2843.     wdwPtr := FindWindow (ownTopWindow);
  2844.     IF wdwPtr # NIL
  2845.     THEN WITH wdwPtr^ DO
  2846.       IF ~isIcon & ~isHidden & (hdlRect # handleRectProc(NIL)) & 
  2847.           hdlRect (wdw, vdi, special, 1, mx, my)
  2848.       THEN 
  2849.         EXCL (event, MagicAES.MUM1);
  2850.         eventDone := TRUE;
  2851.       END;
  2852.     END END;
  2853.   END;
  2854.   IF MagicAES.MUM2 IN event
  2855.   THEN
  2856.     wdwPtr := FindWindow (ownTopWindow);
  2857.     IF wdwPtr # NIL
  2858.     THEN WITH wdwPtr^ DO
  2859.       IF ~isIcon & ~isHidden & (hdlRect # handleRectProc(NIL)) & 
  2860.           hdlRect (wdw, vdi, special, 2, mx, my)
  2861.       THEN 
  2862.         EXCL (event, MagicAES.MUM2);
  2863.         eventDone := TRUE;
  2864.       END;
  2865.     END END;
  2866.   END;
  2867.   IF MagicAES.MUMESAG IN event THEN
  2868.     evtDone := MessageEvent (ADR(pbuff));
  2869.     IF evtDone THEN 
  2870.       EXCL (event, MagicAES.MUMESAG); 
  2871.     ELSIF (handleGlobalMess # handleMessProc (NIL))
  2872.     THEN
  2873.       (* Wenn noch nicht behandelt, dann gehen die an den globalen 
  2874.        * Handler, falls installiert 
  2875.        *)
  2876.       evtDone := handleGlobalMess (ADR(pbuff), kstate);
  2877.       IF evtDone THEN 
  2878.         EXCL (event, MagicAES.MUMESAG); 
  2879.       END;
  2880.     END;
  2881.     eventDone := eventDone OR evtDone;
  2882.   END;
  2883.   IF MagicAES.MUBUTTON IN event
  2884.   THEN
  2885.     r.x := MagicAES.WindFind (mx, my);
  2886.     wdwPtr := FindWindow (r.x);
  2887.     IF wdwPtr # NIL
  2888.     THEN WITH wdwPtr^ DO
  2889.       IF ~isIcon & ~isHidden & (hdlButton # handleButtonProc (NIL)) & hdlButton (wdw, vdi, special, mx, my, kstate, buts, clicks)
  2890.       THEN 
  2891.         EXCL (event, MagicAES.MUBUTTON);
  2892.         eventDone := TRUE;
  2893.       END;
  2894.     END END;
  2895.   END;
  2896.   IF MagicAES.MUTIMER IN event
  2897.   THEN
  2898.     wdwPtr := windows;
  2899.     WHILE wdwPtr # NIL DO
  2900.       WITH wdwPtr^ DO
  2901.         IF ~isIcon & ~isHidden
  2902.         THEN
  2903.           eventDone := eventDone OR ((hdlTimer # handleTimerProc(NIL)) & hdlTimer (wdw, vdi, special));
  2904.         END;
  2905.       END;
  2906.       wdwPtr := wdwPtr^.next;
  2907.     END;
  2908.   END;
  2909.   IF handlePostEvent # handleEventProc(NIL)
  2910.   THEN
  2911.     handlePostEvent (theTopWindow);
  2912.   END;
  2913.   RETURN eventDone
  2914. END HandleEvent;
  2915.  
  2916. PROCEDURE HandlePendingEvents();
  2917.   VAR etv   : BITSET;
  2918.       event : BITSET;
  2919.       mess  : ARRAY [0..7] OF INTEGER;
  2920.       key, 
  2921.       scan  : CHAR;
  2922.       buts, 
  2923.       kstate: BITSET;
  2924.       iScan,
  2925.       taste,
  2926.       mx,
  2927.       my, 
  2928.       clicks: INTEGER;
  2929. BEGIN
  2930.   REPEAT
  2931.     event := MagicAES.EvntMulti(
  2932.                    {MagicAES.MUMESAG, MagicAES.MUTIMER},
  2933.                     0, {},{}, 0, v.r, 0, v.r, mess, 50, 0,
  2934.                     mx, my, buts, taste, kstate, iScan, key, clicks);
  2935.     etv := event;
  2936.     IF MagicAES.MUMESAG IN event
  2937.     THEN
  2938.       MagicAES.WindUpdate(MagicAES.BEGUPDATE);
  2939.       scan := CHR(iScan);
  2940.       v.bool := HandleEvent (event, mess, buts, kstate, key, scan, taste, mx, my, clicks);
  2941.       MagicAES.WindUpdate(MagicAES.ENDUPDATE);
  2942.     END;
  2943.   UNTIL ~(MagicAES.MUMESAG IN etv);
  2944. END HandlePendingEvents;
  2945.  
  2946. PROCEDURE GetTopWindow (VAR wdw, handle : INTEGER);
  2947.   VAR r : Rectangle;
  2948.       wdwPtr : ptrWdwSlot;
  2949. BEGIN
  2950.   MagicAES.WindGet (0, MagicAES.WFTOP, r);
  2951.   wdw := r.x;
  2952.   theTopWindow := wdw;
  2953.   wdwPtr := FindWindow (wdw);
  2954.   IF wdwPtr # NIL
  2955.   THEN
  2956.     handle := wdwPtr^.vdi;
  2957.     wdwPtr^.isTop := TRUE;
  2958.   ELSE
  2959.     handle := -1
  2960.   END;
  2961. END GetTopWindow;
  2962.  
  2963. PROCEDURE IsOwnTop (): BOOLEAN;
  2964. (* Liefert zurck, ob ein eigenes Fenster, das vom Windowmanager verwaltet
  2965.  * wird, das Topwindow ist
  2966.  *)
  2967.  VAR r : Rectangle;
  2968.      wdwPtr : ptrWdwSlot;
  2969. BEGIN
  2970.   MagicAES.WindGet (0, MagicAES.WFTOP, r);
  2971.   theTopWindow := r.x;
  2972.   wdwPtr := FindWindow (theTopWindow);
  2973.   RETURN wdwPtr # NIL;
  2974. END IsOwnTop;
  2975.  
  2976. PROCEDURE WindowIsIcon (wdw: INTEGER) : BOOLEAN;
  2977. (* Liefert TRUE, wenn das Window vorhanden und iconifiziert ist 
  2978.  *)
  2979.   VAR wdwPtr : ptrWdwSlot;
  2980. BEGIN
  2981.   wdwPtr := FindWindow (wdw);
  2982.   IF wdwPtr # NIL
  2983.   THEN
  2984.     RETURN wdwPtr^.isIcon
  2985.   END;
  2986.   RETURN FALSE
  2987. END WindowIsIcon;
  2988.  
  2989. PROCEDURE ModalWindowTop (): BOOLEAN;
  2990. (* Liefert TRUE, wenn das Topwindow ein eigenes und modal ist 
  2991.  *)
  2992. BEGIN
  2993.   RETURN IsOwnTop() & (onlyOneTop >= 0) & (onlyOneTop = theTopWindow);
  2994. END ModalWindowTop;
  2995.  
  2996. PROCEDURE WindowIsShaded (wdw: INTEGER) : BOOLEAN;
  2997. (* Liefert TRUE, wenn das Window vorhanden und mittels WindowShade 
  2998.  * geshadet ist (oder aužerhalb des Bildschirms liegt)
  2999.  *)
  3000.   VAR wdwPtr : ptrWdwSlot;
  3001.       isShaded: BOOLEAN;
  3002.       work   : Rectangle;
  3003. BEGIN
  3004.   wdwPtr := FindWindow (wdw);
  3005.   IF wdwPtr # NIL
  3006.   THEN
  3007.     isShaded := ~RectList (wdw, 0, work);
  3008.     IF ~isShaded
  3009.     THEN
  3010.       (* Rechteckliste bis zum Ende abklappern 
  3011.        *)
  3012.       REPEAT UNTIL ~RectList (wdw, 1, work);
  3013.     END;
  3014.     RETURN isShaded;
  3015.   END;
  3016.   RETURN FALSE
  3017. END WindowIsShaded;
  3018.  
  3019. PROCEDURE WindowIsCloseable (wdw: INTEGER) : BOOLEAN;
  3020. (* Liefert TRUE, wenn das Window vorhanden und schliežbar ist.
  3021.  * Schliežbar heižt, es hat einen Closer.
  3022.  *)
  3023.   VAR wdwPtr : ptrWdwSlot;
  3024. BEGIN
  3025.   wdwPtr := FindWindow (wdw);
  3026.   IF wdwPtr # NIL
  3027.   THEN
  3028.     RETURN (MagicAES.CLOSER IN wdwPtr^.comps);
  3029.   END;
  3030.   RETURN IsInQueue (wdw);
  3031. END WindowIsCloseable;
  3032.  
  3033. PROCEDURE WindowIsFullable (wdw: INTEGER) : BOOLEAN;
  3034. (* Liefert TRUE, wenn das Window vorhanden und fullbar ist,
  3035.  * d.h. es hat einen Sizer oder es ist nur in der Queue drin.
  3036.  *)
  3037.   VAR wdwPtr : ptrWdwSlot;
  3038. BEGIN
  3039.   wdwPtr := FindWindow (theTopWindow);
  3040.   IF wdwPtr # NIL
  3041.   THEN
  3042.     RETURN (MagicAES.Size IN wdwPtr^.comps) & 
  3043.            (MagicAES.FULL IN wdwPtr^.comps);
  3044.   END;
  3045.   RETURN IsInQueue (wdw);
  3046. END WindowIsFullable;
  3047.  
  3048. PROCEDURE ClickInWindow (x, y: INTEGER; VAR wdw: INTEGER);
  3049. (* Liefert das Windowhandle zurck, falls sich an der Position 
  3050.  * x,y ein Fenster befindet (muž nicht dem Modul bekannt sein!)
  3051.  *)
  3052. BEGIN
  3053.   wdw := MagicAES.WindFind (x, y);
  3054. END ClickInWindow;
  3055.  
  3056. (*------- Menu & Keyboard -----------------------------------------------------*)
  3057.  
  3058. PROCEDURE InstallGlobalMenu (tree: ADDRESS; menuP: handleMessProc);
  3059. (* Gibt dem Modul die Adresse des Menubaums bekannt. Damit kann dieser dann disablet
  3060.  * werden, wenn ein modaler Dialog aufgerufen wird.
  3061.  * Aužerdem wird eine Callback-Funktion installiert, die bei Menu-Events aufgerufen
  3062.  * wird.
  3063.  * Es wird nur ein Menu und eine Callbackfunktion verwendet, ein Deinstall
  3064.  * ist daher nicht notwendig, ein erneuter Aufruf berschreibt die
  3065.  * eingestellten Werte
  3066.  *)
  3067. BEGIN
  3068.   globalMenu := tree;
  3069.   handleGlobalMess := menuP;
  3070. END InstallGlobalMenu;
  3071.  
  3072. PROCEDURE DisableMenu (menu: ADDRESS; disable : BOOLEAN);
  3073. (* Schaltet einen Menubaum auf enabled oder disabled 
  3074.  * menu = NIL: ein installiertes globales Menu wird disabled oder enabled
  3075.  *)
  3076. VAR o, title  : INTEGER;
  3077.     t         : mtUtils.tObjcTree;
  3078.     n         : ADDRESS;
  3079.  
  3080. BEGIN
  3081.   IF menu = NIL
  3082.   THEN
  3083.     menu := globalMenu;
  3084.   END;
  3085.   IF menu = NIL
  3086.   THEN
  3087.     RETURN
  3088.   END;
  3089.   IF disable 
  3090.   THEN
  3091.     INC (disableCounter);
  3092.   ELSE
  3093.     DEC (disableCounter);
  3094.   END;
  3095.   IF disable & (disableCounter > 1) THEN RETURN END;
  3096.   IF ~disable & (disableCounter > 0) THEN RETURN END;
  3097.   IF menuDisabled = disable THEN RETURN END;
  3098.  
  3099.   t:= menu;
  3100.   title:= t^[t^[t^[0].obHead].obHead].obHead; (* Index erster Titel *)
  3101.   o := MagicAES.MenuBar(menu, MagicAES.Reset);
  3102.  
  3103.   o:=  t^[t^[t^[0].obHead].obNext].obHead; (* Index erste Box *)
  3104.   mtUtils.SetState(t, t^[o].obHead, MagicAES.DISABLED, disable); (* ersten Eintrag *)
  3105.  
  3106.   LOOP (* 1 *)
  3107.     IF title > t^[title].obNext THEN  EXIT; (* LOOP 1 *) END;
  3108.     title:= t^[title].obNext;
  3109.     mtUtils.SetState(t, title, MagicAES.DISABLED, disable); (* titel disablen *)
  3110.     mtUtils.ExclState(t, title, MagicAES.SELECTED);         (* deselektieren *)
  3111.   END; (* LOOP 1 *)
  3112.  
  3113.   IF disable
  3114.   THEN
  3115.     menuLength := t^[2].obWidth;
  3116.     t^[2].obWidth:= t^[3].obWidth; (* Breite auf DESK begrenzen *)
  3117.   ELSE
  3118.     t^[2].obWidth:= menuLength; (* Breite zurcksetzen *)
  3119.   END;
  3120.  
  3121.   o := MagicAES.MenuBar(menu, MagicAES.Set);
  3122.   menuDisabled := disable;
  3123. END DisableMenu;
  3124.  
  3125. PROCEDURE InstallGlobalKeyProc (key  : handleGlobalKeyProc);
  3126. (* Installiert einen globalen Keyhandler, der dann aufgerufen wird, wenn
  3127.  * die Taste von keinem Fenster behandelt wurde.
  3128.  * Wenn Shift und eine andere Sondertaste gedrckt wird, dann wird 
  3129.  * diese Callback-Funktion vor den Fenstern aufgerufen
  3130.  *)
  3131. BEGIN
  3132.   handleGlobalKey := key;
  3133. END InstallGlobalKeyProc;
  3134.  
  3135. (*------- QueueModul ----------------------------------------------------------*)
  3136. CONST maxQueueEntries = 255;
  3137.  
  3138. TYPE queueEntry = RECORD
  3139.                     wdw  : INTEGER;
  3140.                     apId : INTEGER;
  3141.                   END;
  3142.                   
  3143. VAR handleArray : ARRAY[0..maxQueueEntries] OF queueEntry;
  3144.     maxQueue    : CARDINAL;
  3145.  
  3146. PROCEDURE InitQueue();
  3147. VAR z : CARDINAL;
  3148. BEGIN
  3149.   FOR z := 0 TO maxQueueEntries DO handleArray[z].wdw := -999 END;
  3150.   maxQueue := 0;
  3151. END InitQueue;
  3152.  
  3153. PROCEDURE GetApId (wdw : INTEGER; VAR apId : INTEGER) : BOOLEAN;
  3154.  VAR z : INTEGER;
  3155.      info       : ARRAY [0..3] OF INTEGER;
  3156. BEGIN
  3157.   (* Application ID rausfinden *)
  3158.   IF ((multiTOS OR (magIx & (magIxVer > $200))) 
  3159.   &   (wdw > 0))
  3160.   THEN 
  3161.     MagicAES.WindGet (wdw, MagicAES.WFOWNER, info);
  3162.     IF MagicAES.CallResult # 0 THEN 
  3163.       apId := info[0];
  3164.       RETURN TRUE;
  3165.     END;
  3166.   END;
  3167.   FOR z := 0 TO INTEGER(maxQueue)-1 DO
  3168.     IF handleArray[z].wdw = wdw
  3169.     THEN 
  3170.       apId := handleArray[z].apId;
  3171.       RETURN TRUE
  3172.     END;
  3173.   END;
  3174.   RETURN FALSE;
  3175. END GetApId;
  3176.  
  3177. PROCEDURE EnQueue(wdw, apId : INTEGER; reverse : BOOLEAN);
  3178.   VAR z : INTEGER;
  3179. BEGIN
  3180.   IF reverse
  3181.   THEN
  3182.     INC(maxQueue);
  3183.     FOR z := INTEGER(maxQueue)-2 TO 0 BY -1 DO
  3184.       handleArray[z+1] := handleArray[z];
  3185.     END;
  3186.     handleArray[0].wdw := wdw;
  3187.     handleArray[0].apId:= apId;
  3188.   ELSE
  3189.     handleArray[maxQueue].wdw := wdw;
  3190.     handleArray[maxQueue].apId:= apId;
  3191.     INC(maxQueue);
  3192.   END;
  3193. END EnQueue;
  3194.  
  3195. PROCEDURE DeleteFromQueue(item : INTEGER);
  3196. VAR z : CARDINAL;
  3197.     newState : BITSET;
  3198. BEGIN
  3199.   z := 0;
  3200.   WHILE (z < maxQueue) & (handleArray[z].wdw # item) DO INC(z) END;
  3201.   IF (z < maxQueue) & (handleArray[z].wdw = item) THEN
  3202.     FOR z := z TO maxQueue DO handleArray[z] := handleArray[z+1] END;
  3203.     handleArray[maxQueue].wdw := -999;
  3204.     DEC(maxQueue);
  3205.   END;
  3206. END DeleteFromQueue;
  3207.  
  3208. PROCEDURE TopOfQueue(VAR item, apId : INTEGER);
  3209. BEGIN
  3210.   item := handleArray[0].wdw;
  3211.   apId := handleArray[0].apId;
  3212. END TopOfQueue;
  3213.  
  3214. PROCEDURE FindSpecialTop (proc: queueTestProc): INTEGER;
  3215.   VAR i: INTEGER;
  3216. BEGIN
  3217.   FOR i := INTEGER(maxQueue) -1 TO 0 BY -1 DO
  3218.     IF (handleArray[i].apId = mtAppl.ApplIdent)
  3219.      & proc (handleArray[i].wdw)
  3220.     THEN
  3221.       RETURN handleArray[i].wdw;
  3222.     END;
  3223.   END;
  3224.   RETURN -1;
  3225. END FindSpecialTop;
  3226.  
  3227. PROCEDURE BottomOfQueue(VAR item, apId : INTEGER);
  3228. BEGIN
  3229.   IF maxQueue >= 1
  3230.   THEN
  3231.     item := handleArray[maxQueue-1].wdw;
  3232.     apId := handleArray[maxQueue-1].apId;
  3233.   ELSE
  3234.     item := handleArray[0].wdw;
  3235.     apId := handleArray[0].apId;
  3236.   END;
  3237. END BottomOfQueue;
  3238.  
  3239. PROCEDURE EmptyQueue():BOOLEAN;
  3240. BEGIN
  3241.   RETURN maxQueue = 0
  3242. END EmptyQueue;
  3243.  
  3244. PROCEDURE NewWindowIsTop(handle, apId : INTEGER);
  3245. BEGIN
  3246.   DeleteFromQueue(handle);
  3247.   EnQueue(handle, apId, FALSE);
  3248.   IF handleNewTop # handleNewTopProc (NIL)
  3249.   THEN
  3250.     handleNewTop (handle);
  3251.   END;
  3252. END NewWindowIsTop;
  3253.  
  3254. PROCEDURE BringToBottom(handle, apId : INTEGER);
  3255. BEGIN
  3256.   DeleteFromQueue(handle);
  3257.   EnQueue(handle, apId, TRUE);
  3258. END BringToBottom;
  3259.  
  3260. PROCEDURE WindowIsClosed(handle : INTEGER);
  3261. BEGIN
  3262.   DeleteFromQueue(handle)
  3263. END WindowIsClosed;
  3264.  
  3265. PROCEDURE SendRedraw (win: INTEGER; r : Rectangle);
  3266. TYPE messArray = RECORD
  3267.                    mid, 
  3268.                    apid,
  3269.                    over,
  3270.                    wdw  : INTEGER;
  3271.                    area : Rectangle;
  3272.                  END;
  3273. VAR mess : messArray;
  3274.     apId : INTEGER;
  3275. BEGIN
  3276.   v.bool := GetApId (win, apId);
  3277.   mess := messArray{MagicAES.WMREDRAW, mtAppl.ApplIdent, 0, win, r};
  3278.   MagicAES.ApplWrite(apId, 16, mess);
  3279. END SendRedraw;
  3280.  
  3281. PROCEDURE SendMess (win, apId, msg : INTEGER);
  3282. TYPE msgArray = RECORD
  3283.                   mid,
  3284.                   apid,
  3285.                   over,
  3286.                   wdw   : INTEGER;
  3287.                   r1,
  3288.                   r2    : LONGINT;
  3289.                 END;
  3290. VAR mess : msgArray;
  3291. BEGIN
  3292.   mess := msgArray{msg, mtAppl.ApplIdent, 0, win, 0, 0};
  3293.   MagicAES.ApplWrite(apId, 16, mess);
  3294. END SendMess;
  3295.  
  3296. PROCEDURE SendTop(win, apId : INTEGER);
  3297. BEGIN
  3298.   SendMess (win, apId, MagicAES.WMTOPPED);
  3299. END SendTop;
  3300.  
  3301. PROCEDURE SendClosed(win, apId : INTEGER);
  3302. BEGIN
  3303.   SendMess (win, apId, MagicAES.WMCLOSED);
  3304. END SendClosed;
  3305.  
  3306. PROCEDURE SendFulled (win, apId : INTEGER);
  3307. BEGIN
  3308.   SendMess (win, apId, MagicAES.WMFULLED);
  3309. END SendFulled;
  3310.  
  3311. PROCEDURE TopNextWindow();
  3312. VAR nextTop, apId : INTEGER;
  3313.     wdwPtr        : ptrWdwSlot;
  3314. BEGIN
  3315.   IF ~EmptyQueue() THEN
  3316.     TopOfQueue(nextTop, apId);
  3317.     IF (nextTop # -999) THEN
  3318.       IF nextTop >= 0 THEN
  3319.         wdwPtr := FindWindow (nextTop);
  3320.         IF wdwPtr # NIL
  3321.         THEN
  3322.           topWdw (wdwPtr, TRUE);
  3323.         ELSE
  3324.           SendTop(nextTop, apId);
  3325.           NewWindowIsTop(nextTop, apId);
  3326.         END
  3327.       END;
  3328.     END;
  3329.   END;
  3330. END TopNextWindow;
  3331.  
  3332. PROCEDURE TopLastWindow();
  3333. VAR nextTop, apId : INTEGER;
  3334.     wdwPtr        : ptrWdwSlot;
  3335. BEGIN
  3336.   IF ~EmptyQueue() THEN
  3337.     BottomOfQueue(nextTop, apId);
  3338.     IF (nextTop # -999) THEN
  3339.       IF nextTop >= 0 THEN
  3340.         wdwPtr := FindWindow (nextTop);
  3341.         IF wdwPtr # NIL
  3342.         THEN
  3343.           topWdw (wdwPtr, TRUE);
  3344.         ELSE
  3345.           SendTop(nextTop, apId);
  3346.           NewWindowIsTop(nextTop, apId);
  3347.         END
  3348.       END;
  3349.     END;
  3350.   END;
  3351. END TopLastWindow;
  3352.  
  3353. PROCEDURE GetOwnTopWindow (VAR wdw: INTEGER);
  3354.   VAR i : INTEGER;
  3355.       wdwPtr : ptrWdwSlot;
  3356. BEGIN
  3357.   IF ~EmptyQueue() THEN
  3358.     FOR i := maxQueue-1 TO 0 BY -1 DO
  3359.       wdw := handleArray[i].wdw;
  3360.       IF wdw >= 0
  3361.       THEN
  3362.         wdwPtr := FindWindow (wdw);
  3363.         IF wdwPtr # NIL
  3364.         THEN
  3365.           RETURN
  3366.         END;
  3367.       END;
  3368.     END;
  3369.   END;
  3370.   wdw := -1;
  3371. END GetOwnTopWindow;
  3372.  
  3373. PROCEDURE TopNextPossible() : BOOLEAN;
  3374. BEGIN
  3375.   RETURN maxQueue >= 1
  3376. END TopNextPossible;
  3377.  
  3378. PROCEDURE IsInQueue (wdw : INTEGER) : BOOLEAN;
  3379. (* Liefert TRUE zurck, wenn das Fenster wdw in 
  3380.  * der verwalteten Queue ist.
  3381.  *)
  3382. BEGIN
  3383.   RETURN GetApId (wdw, v.int);
  3384. END IsInQueue;
  3385.  
  3386. PROCEDURE GetSecondWdw (VAR wdw : INTEGER): BOOLEAN;
  3387. (* Liefert zweitoberstes Fenster zurck.
  3388.  * Geht nur ber Queue, benutzt nicht die Liste.
  3389.  *)
  3390. BEGIN
  3391.   IF maxQueue <= 1 THEN RETURN FALSE; END;
  3392.   wdw := handleArray[maxQueue-2].wdw;
  3393.   RETURN TRUE;
  3394. END GetSecondWdw;
  3395.  
  3396. PROCEDURE ArrangeWindows (mode : INTEGER);
  3397. (* Ordnet die Fenster 
  3398.  *)
  3399.  VAR wdwPtr : ptrWdwSlot;
  3400.      i,
  3401.      wdws : INTEGER;
  3402.      newSize : Rectangle;
  3403.      cols, rows,
  3404.      xcols, xrows : INTEGER;
  3405. BEGIN
  3406.   wdws := 0;
  3407.   (* Fenster z„hlen *)
  3408.   wdwPtr := windows;
  3409.   WHILE wdwPtr # NIL DO
  3410.     IF (MagicAES.Size IN wdwPtr^.comps) & 
  3411.         ~wdwPtr^.isIcon &
  3412.         ~wdwPtr^.isHidden
  3413.     THEN INC (wdws); END;
  3414.     wdwPtr := wdwPtr^.next;
  3415.   END;
  3416.   IF wdws <= 1 THEN RETURN END;
  3417.   i := 1;
  3418.   wdwPtr := windows;
  3419.   (* Letzten Eintrag suchen *)
  3420.   WHILE wdwPtr^.next # NIL DO
  3421.     wdwPtr := wdwPtr^.next
  3422.   END;
  3423.   CASE mode OF 
  3424.     STACKED : WHILE (i <= wdws) & (wdwPtr # NIL) DO 
  3425.                 IF (MagicAES.Size IN wdwPtr^.comps)
  3426.                  & ~wdwPtr^.isIcon & ~wdwPtr^.isHidden
  3427.                 THEN
  3428.                   WITH newSize DO
  3429.                     x := deskSize.x;                                      (* new.x *)
  3430.                     y := deskSize.y + (i-1) * (deskSize.h DIV wdws);      (* new.y *)
  3431.                     w := deskSize.w;                                      (* new.w *)
  3432.                     h := deskSize.h DIV wdws;                             (* new.h *)
  3433.                   END;
  3434.                   moveSizeWdw (wdwPtr, TRUE, FALSE, newSize, TRUE);
  3435.                   INC (i);
  3436.                 END;
  3437.                 wdwPtr := wdwPtr^.prev;
  3438.               END; |
  3439.     BYSIDE  : WHILE (i <= wdws) & (wdwPtr # NIL) DO 
  3440.                 IF (MagicAES.Size IN wdwPtr^.comps)
  3441.                  & ~wdwPtr^.isIcon & ~wdwPtr^.isHidden
  3442.                 THEN
  3443.                   WITH newSize DO
  3444.                     x := deskSize.x + (i-1) * (deskSize.w DIV wdws);      (* new.x *)
  3445.                     y := deskSize.y;                                      (* new.y *)
  3446.                     w := deskSize.w DIV wdws;                             (* new.w *)
  3447.                     h := deskSize.h;                                      (* new.h *)
  3448.                   END;
  3449.                   moveSizeWdw (wdwPtr, TRUE, FALSE, newSize, TRUE);
  3450.                   INC (i);
  3451.                 END;
  3452.                 wdwPtr := wdwPtr^.prev;
  3453.               END; |
  3454.     OVERLAP : WHILE (i <= wdws) & (wdwPtr # NIL) DO 
  3455.                 IF (MagicAES.Size IN wdwPtr^.comps)
  3456.                  & ~wdwPtr^.isIcon & ~wdwPtr^.isHidden
  3457.                 THEN
  3458.                   WITH newSize DO
  3459.                     x := deskSize.x + (i-1) * mtAppl.CharHeight;          (* new.x *)
  3460.                     y := deskSize.y + (i-1) * mtAppl.CharHeight;          (* new.y *)
  3461.                     w := deskSize.w - (wdws-1) * mtAppl.CharHeight;       (* new.w *)
  3462.                     h := deskSize.h - (wdws-1) * mtAppl.CharHeight;       (* new.h *)
  3463.                   END;
  3464.                   moveSizeWdw (wdwPtr, TRUE, FALSE, newSize, TRUE);
  3465.                   INC (i);
  3466.                 END;
  3467.                 wdwPtr := wdwPtr^.prev;
  3468.               END; |
  3469.     TILED   : (* Erstmal rausfinden, wieviel Fenster nebeneinander kommen *)
  3470.               cols := 2;
  3471.               WHILE cols*cols < wdws DO INC (cols) END;
  3472.               rows := wdws DIV cols;
  3473.               IF rows * cols < wdws THEN xrows := rows+1 ELSE xrows := rows END;
  3474.               xcols := wdws - (rows * cols);
  3475.               IF xcols = 0 THEN xcols := cols END;
  3476.               WHILE ( (i-1) DIV cols < rows) & (wdwPtr # NIL) DO
  3477.                 IF (MagicAES.Size IN wdwPtr^.comps)
  3478.                  & ~wdwPtr^.isIcon & ~wdwPtr^.isHidden
  3479.                 THEN
  3480.                   WITH newSize DO
  3481.                     x := deskSize.x + ((i-1) MOD cols) * (deskSize.w DIV cols);     (* new.x *)
  3482.                     y := deskSize.y + ((i-1) DIV cols) * (deskSize.h DIV xrows);    (* new.y *)
  3483.                     w := deskSize.w DIV cols;                                       (* new.w *)
  3484.                     h := deskSize.h DIV xrows;                                      (* new.h *)
  3485.                   END;
  3486.                   moveSizeWdw (wdwPtr, TRUE, FALSE, newSize, TRUE);
  3487.                   INC (i);
  3488.                 END;
  3489.                 wdwPtr := wdwPtr^.prev;
  3490.               END;
  3491.               WHILE ( i <= wdws) & (wdwPtr # NIL) DO
  3492.                 IF (MagicAES.Size IN wdwPtr^.comps)
  3493.                  & ~wdwPtr^.isIcon & ~wdwPtr^.isHidden
  3494.                 THEN
  3495.                   WITH newSize DO
  3496.                     x := deskSize.x + ((i-1) MOD xcols) * (deskSize.w DIV xcols);   (* new.x *)
  3497.                     y := deskSize.y + ((i-1) DIV cols) * (deskSize.h DIV xrows);    (* new.y *)
  3498.                     w := deskSize.w DIV xcols;                                      (* new.w *)
  3499.                     h := deskSize.h DIV xrows;                                      (* new.h *)
  3500.                   END;
  3501.                   moveSizeWdw (wdwPtr, TRUE, FALSE, newSize, TRUE);
  3502.                   INC (i);
  3503.                 END;
  3504.                 wdwPtr := wdwPtr^.prev;
  3505.               END; 
  3506.               |
  3507.   ELSE
  3508.   END;
  3509. END ArrangeWindows;
  3510.  
  3511. (*-- Drag & Drop Support fr MTOS ------------------------------------------*)
  3512.  
  3513. PROCEDURE WdwInstallDDClient (wdw: INTEGER; 
  3514.                               getExts : getExtsProc;
  3515.                               acceptData : acceptDataProc;
  3516.                               writeData  : writeDataProc);
  3517. (* Ein Fenster installiert fr sich Drag & Drop. Damit untersttzt
  3518.  * es automatisch Drag & Drop. 
  3519.  *)
  3520.   VAR wdwPtr : ptrWdwSlot;
  3521. BEGIN
  3522.   wdwPtr := FindWindow (wdw);
  3523.   IF wdwPtr # NIL
  3524.   THEN
  3525.     WITH wdwPtr^ DO
  3526.       ddClientInstalled := TRUE;
  3527.       ddGetExts := getExts;
  3528.       ddAcceptData := acceptData;
  3529.       ddWriteData := writeData;
  3530.     END;
  3531.   END;
  3532. END WdwInstallDDClient;
  3533.  
  3534. PROCEDURE WdwInstallDDServer (wdw: INTEGER; 
  3535.                               getHeader : getHeaderProc;
  3536.                               readData  : readDataProc);
  3537. (* Ein Fenster installiert sich als Server fr Drag & Drop. 
  3538.  * Danach kann es dann die Prozedur WdwDDServe benutzen, 
  3539.  * die Drag & Drop durchfhrt.
  3540.  *)
  3541.   VAR wdwPtr : ptrWdwSlot;
  3542. BEGIN
  3543.   wdwPtr := FindWindow (wdw);
  3544.   IF wdwPtr # NIL
  3545.   THEN
  3546.     WITH wdwPtr^ DO
  3547.       ddServerInstalled := TRUE;
  3548.       ddGetHeader := getHeader;
  3549.       ddReadData := readData;
  3550.     END;
  3551.   END;
  3552. END WdwInstallDDServer;
  3553.  
  3554. PROCEDURE WdwDoesDragDrop (wdw: INTEGER): BOOLEAN;
  3555. (* TRUE: Das Fenster untersttzt Drag & Drop 
  3556.  *)
  3557.   VAR wdwPtr : ptrWdwSlot;
  3558. BEGIN
  3559.   wdwPtr := FindWindow (wdw);
  3560.   IF wdwPtr # NIL
  3561.   THEN
  3562.     RETURN wdwPtr^.ddClientInstalled
  3563.   END
  3564. END WdwDoesDragDrop;
  3565.  
  3566. PROCEDURE WdwDDGetExts (wdw: INTEGER; VAR exts: ARRAY OF CHAR);
  3567. (* Liefert fr das Wdw die untersttzen Extensions zurck 
  3568.  *)
  3569.   VAR wdwPtr : ptrWdwSlot;
  3570. BEGIN
  3571.   wdwPtr := FindWindow (wdw);
  3572.   IF wdwPtr # NIL
  3573.   THEN
  3574.     IF wdwPtr^.ddClientInstalled
  3575.     THEN
  3576.       wdwPtr^.ddGetExts (wdw, wdwPtr^.special, exts);
  3577.     END;
  3578.   END;
  3579. END WdwDDGetExts;
  3580.  
  3581. PROCEDURE WdwDDAcceptData (wdw: INTEGER; hdr: ADDRESS): BOOLEAN;
  3582. (* Falls das Window die Daten nach dem Header akzeptiert, dann wird
  3583.  * TRUE zurckgegeben
  3584.  *)
  3585.   VAR wdwPtr : ptrWdwSlot;
  3586. BEGIN
  3587.   wdwPtr := FindWindow (wdw);
  3588.   IF wdwPtr # NIL
  3589.   THEN
  3590.     IF wdwPtr^.ddClientInstalled
  3591.     THEN
  3592.       RETURN wdwPtr^.ddAcceptData (wdw, wdwPtr^.special, hdr);
  3593.     END;
  3594.   END;
  3595.   RETURN FALSE
  3596. END WdwDDAcceptData;
  3597.  
  3598. PROCEDURE WdwDDWriteData (wdw: INTEGER; VAR data: ADDRESS; dataLen: LONGCARD);
  3599. (* Die Daten werden an das Fenster bergeben 
  3600.  *)
  3601.   VAR wdwPtr : ptrWdwSlot;
  3602. BEGIN
  3603.   wdwPtr := FindWindow (wdw);
  3604.   IF wdwPtr # NIL
  3605.   THEN
  3606.     IF wdwPtr^.ddClientInstalled
  3607.     THEN
  3608.       wdwPtr^.ddWriteData (wdw, wdwPtr^.special, data, dataLen);
  3609.     END;
  3610.   END;
  3611. END WdwDDWriteData;
  3612.  
  3613. (*
  3614.  * create a pipe for doing the drag & drop,
  3615.  * and send an AES message to the receipient
  3616.  * application telling it about the drag & drop
  3617.  * operation.
  3618.  *
  3619.  * Input Parameters:
  3620.  * apid:    AES id of the window owner
  3621.  * winid:   target window (0 for background)
  3622.  * msx, msy:    mouse X and Y position
  3623.  *      (or -1, -1 if a fake drag & drop)
  3624.  * kstate:  shift key state at time of event
  3625.  *
  3626.  * Output Parameters:
  3627.  * exts:    A 32 byte buffer into which the
  3628.  *      receipient's 8 favorite
  3629.  *      extensions will be copied.
  3630.  *
  3631.  * Returns:
  3632.  * A positive file descriptor (of the opened
  3633.  * drag & drop pipe) on success.
  3634.  * -1 if the receipient doesn't respond or
  3635.  *    returns DD_NAK
  3636.  * -2 if appl_write fails
  3637.  *)
  3638.  
  3639. PROCEDURE WdwDDCreate (apId, wdw, mx, my : INTEGER; kstate: BITSET;
  3640.                        VAR exts: ARRAY OF CHAR; VAR oldPipe: ADDRESS): INTEGER;
  3641. TYPE msgArray = RECORD
  3642.                   mid,
  3643.                   apid,
  3644.                   over,
  3645.                   win,
  3646.                   x, 
  3647.                   y     : INTEGER;
  3648.                   kbd   : BITSET;
  3649.                   ch1,
  3650.                   ch2   : CHAR;
  3651.                 END;
  3652. VAR fd, i   : INTEGER;
  3653.     msg     : msgArray;
  3654.     fdMask  : MagicSys.lBITSET;
  3655.     c       : CHAR;
  3656.     pipename: ARRAY [0..255] OF CHAR;
  3657.     count   : LONGCARD;
  3658. BEGIN
  3659.   (* create pipe *)
  3660.   Strings.Assign ('U:\PIPE\DRAGDROP.AA', pipename, v.bool);
  3661.   fd := -1;
  3662.   LOOP
  3663.     INC (pipename[18]);
  3664.     IF pipename[18] > 'Z'
  3665.     THEN
  3666.       INC (pipename[17]);
  3667.       IF pipename[17] > 'Z' THEN
  3668.         EXIT 
  3669.       END;
  3670.     END;
  3671.     (* HIDDEN means "get EOF if nobody has pipe open for reading" *)
  3672.     fd := MagicDOS.Fcreate (pipename, {MagicDOS.Hidden});
  3673.     IF fd # MagicDOS.EAccDn THEN EXIT END;
  3674.   END;
  3675.   (* test file handle *)
  3676.   IF fd < 0
  3677.   THEN
  3678.     (* Fcreate error *)
  3679.     RETURN fd
  3680.   END;
  3681.   (* set SIG_PIPE to SIG_IGN *)
  3682.   oldPipe := Mintbind.Psignal (Mintbind.SIGPIPE, Mintbind.SIG_IGN);
  3683.   
  3684.   (* construct and send the AES message *)
  3685.   msg := msgArray{MagicAES.AP_DRAGDROP, mtAppl.ApplIdent, 0, wdw, mx, my, 
  3686.                   kstate,pipename[17],pipename[18]};
  3687.   MagicAES.ApplWrite(apId, 16, msg);
  3688.  
  3689.   (* now wait for a response *)
  3690.   fdMask := MagicSys.lBITSET{fd};
  3691.   v.lcard := 0;
  3692.   i := Mintbind.Fselect ( (*MagicAES.DD_TIMEOUT*) 1000, fdMask, v.lbset, 0);
  3693.   IF (i=0) OR (fdMask = MagicSys.lBITSET{})
  3694.   THEN
  3695.     (* timeout happened *)
  3696.     v.a := Mintbind.Psignal (Mintbind.SIGPIPE, oldPipe);
  3697.     v.int := MagicDOS.Fclose (fd);
  3698.     RETURN -1;
  3699.   END;
  3700.   
  3701.   (* read the 1 byte response *)
  3702.   count := 1;
  3703.   MagicDOS.Fread (fd, count, ADR(c));
  3704.   IF (count # 1) OR (ORD(c) # MagicAES.DD_OK)
  3705.   THEN
  3706.     (* no drag & drop *)
  3707.     v.a := Mintbind.Psignal (Mintbind.SIGPIPE, oldPipe);
  3708.     v.int := MagicDOS.Fclose (fd);
  3709.     RETURN -1;
  3710.   END;
  3711.   (* now read the "preferred extensions" *)
  3712.   count := MagicAES.DD_EXTSIZE;
  3713.   MagicDOS.Fread(fd, count, ADR(exts));
  3714.   IF count # MagicAES.DD_EXTSIZE
  3715.   THEN
  3716.     (* Read error in pipe *)
  3717.     v.a := Mintbind.Psignal (Mintbind.SIGPIPE, oldPipe);
  3718.     v.int := MagicDOS.Fclose (fd);
  3719.     RETURN -1
  3720.   END;
  3721.  
  3722.   (* init was ok *)
  3723.   RETURN fd
  3724. END WdwDDCreate;
  3725.  
  3726. (*
  3727.  * see if the receipient is willing to accept a certain
  3728.  * type of data (as indicated by "ext")
  3729.  *
  3730.  * Input parameters:
  3731.  * fd       file descriptor returned from ddcreate()
  3732.  * ext      pointer to the 4 byte file type
  3733.  * name     pointer to the name of the data
  3734.  * size     number of bytes of data that will be sent
  3735.  *
  3736.  * Output parameters: none
  3737.  *
  3738.  * Returns:
  3739.  * DD_OK    if the receiver will accept the data
  3740.  * DD_EXT   if the receiver doesn't like the data type
  3741.  * DD_LEN   if the receiver doesn't like the data size
  3742.  * DD_NAK   if the receiver aborts
  3743.  *)
  3744.  
  3745. PROCEDURE WdwDDstry (fd: INTEGER; REF ext, name: ARRAY OF CHAR; size: LONGCARD): INTEGER;
  3746.   VAR hdrLen, i : INTEGER;
  3747.       fdMask    : MagicSys.lBITSET;
  3748.       c         : CHAR;
  3749.       count     : LONGCARD;
  3750. BEGIN
  3751.   (*$W-*)
  3752.   (* 4 bytes for extension, 4 bytes for size, 1 byte for
  3753.    * trailing 0
  3754.    *)
  3755.   hdrLen := 9 + LENGTH(name);
  3756.   count := 2;
  3757.   MagicDOS.Fwrite(fd, count, ADR(hdrLen));
  3758.   IF count # 2 THEN RETURN MagicAES.DD_NAK END;
  3759.   
  3760.   (* now send the header *)
  3761.   count := 4;
  3762.   MagicDOS.Fwrite (fd, count, ADR(ext));
  3763.   i := SHORT(count);
  3764.   count := 4;
  3765.   MagicDOS.Fwrite (fd, count, ADR(size));
  3766.   INC (i, count);
  3767.   count := LENGTH (name) + 1;
  3768.   MagicDOS.Fwrite (fd, count, ADR(name));
  3769.   INC (i, count);
  3770.   IF i # hdrLen THEN RETURN MagicAES.DD_NAK END;
  3771.   
  3772.   (* now wait for a response *)
  3773.   fdMask := MagicSys.lBITSET{fd};
  3774.   v.lcard := 0;
  3775.   (* wait to a maximum of 100 ms *)
  3776.   i := Mintbind.Fselect (100, fdMask, v.lbset, 0);
  3777.   IF (i=0) OR (fdMask = MagicSys.lBITSET{})
  3778.   THEN
  3779.     (* timeout happened *)
  3780.     RETURN MagicAES.DD_NAK;
  3781.   END;
  3782.  
  3783.   (* wait for a reply *)
  3784.   count := 1;
  3785.   MagicDOS.Fread(fd, count, ADR(c));
  3786.   IF (i # 1) THEN RETURN MagicAES.DD_NAK; END;
  3787.   RETURN ORD(c);
  3788.   (*$W=*)
  3789. END WdwDDstry;
  3790.  
  3791. (*
  3792.  * close a drag & drop operation
  3793.  *)
  3794.  
  3795. PROCEDURE WdwDDclose (fd: INTEGER; oldPipe: ADDRESS);
  3796. BEGIN
  3797.   (* restore signal handler *)
  3798.   v.a := Mintbind.Psignal (Mintbind.SIGPIPE, oldPipe);
  3799.   (* close pipe *)
  3800.   v.int := MagicDOS.Fclose (fd);
  3801. END WdwDDclose;
  3802.  
  3803. PROCEDURE WdwInternalDD (server, client: ptrWdwSlot);
  3804. VAR   hdr   : POINTER TO RECORD
  3805.                 dtype : ARRAY [0..3] OF CHAR;
  3806.                 dlen  : LONGCARD;
  3807.                 dname : ARRAY [0..2047] OF CHAR;
  3808.               END;
  3809.      ext        : ARRAY [0..3] OF CHAR;
  3810.      name       : ARRAY [0..79] OF CHAR;
  3811.      size       : LONGCARD;
  3812.      data       : ADDRESS;
  3813.      done       : BOOLEAN;
  3814. BEGIN
  3815.   WITH server^ DO
  3816.     IF ddGetHeader (wdw, special, HDRFIRST, ext, name, size)
  3817.     THEN
  3818.       done := FALSE;
  3819.       REPEAT 
  3820.         (* Header aufbauen *)
  3821.         ALLOCATE (hdr, 9 + LENGTH (name));
  3822.         IF hdr = NIL THEN RETURN END;
  3823.         hdr^.dtype := ext;
  3824.         hdr^.dlen := size;
  3825.         Strings.Assign (name, hdr^.dname, v.bool);
  3826.         (* Beim Client anfragen, ob er den Header annimmt *)
  3827.         IF client^.ddAcceptData (client^.wdw, client^.special, hdr)
  3828.         THEN
  3829.           (* Daten holen *)
  3830.           ddReadData (wdw, special, data);
  3831.           IF data # NIL
  3832.           THEN
  3833.             client^.ddWriteData (client^.wdw, client^.special, data, size);
  3834.             DEALLOCATE (data, 0);
  3835.             done := TRUE;
  3836.           END;
  3837.         END;
  3838.         DEALLOCATE (hdr, 0);
  3839.       UNTIL done OR ~ddGetHeader (wdw, special, HDRNEXT, ext, name, size);
  3840.     END;
  3841.   END;
  3842. END WdwInternalDD;
  3843.  
  3844. PROCEDURE WdwDDServe (wdw: INTEGER; mx, my: INTEGER; kstate: BITSET): BOOLEAN;
  3845. (* Initialisiert Drag & Drop als Server. wdw ist das Source-Fenster(!!),
  3846.  * vorher muž sich das Fenster als Server angemeldet haben. Dann wird
  3847.  * ber die angemeldeten Prozeduren versucht, Drag & Drop durchzufhren
  3848.  *)
  3849.  VAR wdwPtr,
  3850.      wdwPtr2    : ptrWdwSlot;
  3851.      exts       : ARRAY [0..MagicAES.DD_EXTSIZE-1] OF CHAR;
  3852.      ext        : ARRAY [0..7] OF CHAR;
  3853.      name       : ARRAY [0..79] OF CHAR;
  3854.      tWin       : INTEGER;
  3855.      info       : ARRAY [0..3] OF INTEGER;
  3856.      res,
  3857.      fd         : INTEGER;
  3858.      size       : LONGCARD;
  3859.      oldPipe    : ADDRESS;
  3860.      data       : ADDRESS;
  3861.      fdMask     : MagicSys.lBITSET;
  3862. BEGIN
  3863.   wdwPtr := FindWindow (wdw);
  3864.   IF wdwPtr # NIL
  3865.   THEN
  3866.     IF wdwPtr^.ddServerInstalled
  3867.     THEN
  3868.       (* Ok, wir haben einen Server 
  3869.        * Jetzt das Zielfenster finden 
  3870.        *)
  3871.       tWin := MagicAES.WindFind (mx, my);
  3872.       (* Drag & Drop im gleichen Fenster geht nicht *)
  3873.       IF tWin = wdw THEN RETURN FALSE END;
  3874.       wdwPtr2 := FindWindow (tWin);
  3875.       IF wdwPtr2 # NIL
  3876.       THEN
  3877.         (* Ist eigenes Fenster! Eventuell internes Drag & Drop durchfhren
  3878.          *)
  3879.         IF wdwPtr2^.ddClientInstalled
  3880.         THEN
  3881.           (* Do internal drag & drop *)
  3882.           WdwInternalDD (wdwPtr, wdwPtr2);
  3883.         END;
  3884.         (* Hier k”nnen wir rausgehen, da passiert nichts mehr *)
  3885.         RETURN TRUE
  3886.       END;
  3887.       (* Ok, ist fremdes Fenster *)
  3888.       (* Wenn kein multiTasking OS, dann abbrechen *)
  3889.       IF ~(multiTOS OR (magIx & (magIxVer > $200))) THEN RETURN FALSE END;
  3890.       (* Application ID rausfinden *)
  3891.       MagicAES.WindGet (tWin, MagicAES.WFOWNER, info);
  3892.       IF MagicAES.CallResult = 0 THEN RETURN FALSE END; (* keine Application gefunden *)
  3893.       IF info[0] = mtAppl.ApplIdent THEN RETURN FALSE END; (* this should NOT happen! *)
  3894.       (* create drag & drop pipe *)
  3895.       fd := WdwDDCreate (info[0], tWin, mx, my, kstate, exts, oldPipe);
  3896.       IF fd < 0 THEN 
  3897.         RETURN FALSE
  3898.       END;
  3899.       (* Die gelieferten Extensions ignorieren wir einfach *)
  3900.       (* Beim Server die ersten Headerdaten anfordern *)
  3901.       IF wdwPtr^.ddGetHeader (wdwPtr^.wdw, wdwPtr^.special, HDRFIRST, ext, name, size)
  3902.       THEN
  3903.         REPEAT 
  3904.           (* Header senden und nachsehen, ob es akzeptiert wird *)
  3905.           res := WdwDDstry (fd, ext, name, size);
  3906.           IF res = MagicAES.DD_OK
  3907.           THEN
  3908.             (* Daten holen *)
  3909.             wdwPtr^.ddReadData (wdwPtr^.wdw, wdwPtr^.special, data);
  3910.             IF data # NIL
  3911.             THEN
  3912.               (* Daten schreiben in pipe *)
  3913.               MagicDOS.Fwrite (fd, size, data);
  3914.               (* Speicher freigeben *)
  3915.               DEALLOCATE (data, 0);
  3916.               
  3917.               (* now wait for a response *)
  3918.               fdMask := MagicSys.lBITSET{fd};
  3919.               v.lcard := 0;
  3920.               (* wait a little bit before closing the pipe *)
  3921.               v.int := Mintbind.Fselect (100, fdMask, v.lbset, 0);
  3922.             ELSE
  3923.               (* Fehler beim holen der Daten, abbrechen *)
  3924.               res := MagicAES.DD_NAK;
  3925.             END;
  3926.           ELSE
  3927.             IF (res # MagicAES.DD_NAK) 
  3928.             & ~wdwPtr^.ddGetHeader (wdwPtr^.wdw, wdwPtr^.special, HDRNEXT, ext, name, size)
  3929.             THEN
  3930.               (* DD_EXT or DD_LEN, aber kein weiterer Header, also abbrechen *)
  3931.               res := MagicAES.DD_NAK;
  3932.             END;
  3933.           END;
  3934.         UNTIL (res = MagicAES.DD_OK) OR (res = MagicAES.DD_NAK);
  3935.       END;
  3936.       (* Pipe wieder schliežen *)
  3937.       WdwDDclose(fd, oldPipe);
  3938.       RETURN TRUE;
  3939.     END;
  3940.   END;
  3941.   RETURN FALSE;
  3942. END WdwDDServe;
  3943.  
  3944. PROCEDURE windowTerm();
  3945.   VAR wdwPtr,
  3946.       dummyPtr : ptrWdwSlot;
  3947.       voidO    : BOOLEAN;
  3948. BEGIN
  3949.   wdwPtr := windows;
  3950.   WHILE wdwPtr # NIL DO
  3951.     WITH wdwPtr^ DO
  3952.       voidO := hdlClose(wdw, vdi, special, TRUE);  
  3953.       (* Fenster noch schliežen *)
  3954.       MagicAES.WindClose (wdw);
  3955.       MagicAES.WindDelete (wdw);
  3956.       WindowIsClosed (wdw);
  3957.       (* Workstation schliežen *)
  3958.       IF vdi > 0 THEN 
  3959.         mtAppl.CloseWorkstation (vdi); 
  3960.       END;
  3961.     END;
  3962.     dummyPtr := wdwPtr;
  3963.     wdwPtr := wdwPtr^.next;
  3964.     DISPOSE (dummyPtr);
  3965.   END;
  3966. END windowTerm;
  3967.  
  3968. PROCEDURE EnableIconify (enable: BOOLEAN);
  3969. BEGIN
  3970.   iconifySupportEnabled := enable;
  3971. END EnableIconify;
  3972.  
  3973. PROCEDURE SetMagicPCKeyTranslation (setIt: BOOLEAN);
  3974. (* Schaltet die Tastenbersetzung fr MagicPC ein *)
  3975. BEGIN
  3976.   MagicPCKeyTrans := setIt;
  3977. END SetMagicPCKeyTranslation;
  3978.  
  3979. CONST
  3980.     (* Cookies definieren *)
  3981.     MagiXCookie = 'MagX';
  3982.     MultiGEMCookie = 'MGEM';
  3983.  
  3984. TYPE    magAESVARS = RECORD
  3985.                          magic      : LONGCARD; (* muž $87654321 sein         *)
  3986.                          membot     : ADDRESS;  (* Ende der AES- Variablen    *)
  3987.                          aes_start  : ADDRESS;  (* Startadresse               *)
  3988.                          magic2     : LONGCARD; (* ist 'MAGX'                 *)
  3989.                          date       : LONGCARD; (* Erstelldatum               *)
  3990.                          chgres     : ADDRESS;  (* void ( *chgres)(int res, int txt);  /* Aufl”sung „ndern      *)
  3991.                          shel_vector: ADDRESS;  (* long ( **shel_vector)(void);   /* residentes Desktop         *)
  3992.                          aes_bootdrv: ADDRESS;  (* char *aes_bootdrv;            /* von hieraus wurde gebootet *)
  3993.                          vdi_device : ADDRESS;  (* int  *vdi_device;             /* vom AES benutzter Treiber  *)
  3994.                          (* zus„tzliche Variablen, die nicht dokumentiert sind       *)
  3995.                          nvdi_work  : ADDRESS;  (* void **nvdi_workstation;      /* vom AES benutzte Workstation *)
  3996.                          shelw_doex : ADDRESS;  (* int  *shelw_doex;             /* shel-write variable        *)
  3997.                          shelw_isgr : ADDRESS;  (* int  *shelw_isgr;             /* shel-write variable        *)
  3998.                          version    : INTEGER;  (* int  version;                 /* in Hex 0111 (BCD)          *)
  3999.                          release    : INTEGER;  (* int  release;                 /* +224 = Zeichen der Version *)
  4000.                          _basepage  : LONGCARD;
  4001.                          moff_cnt   : ADDRESS;  (* int  *moff_cnt; *)
  4002.                          shel_buf_len: LONGCARD; (* long shel_buf_len; *)
  4003.                          shel_buf   : ADDRESS;  (* long shel_buf; *)
  4004.                          ntrdy_list : LONGCARD; (* long notready_list; *)
  4005.                          menu_up    : LONGCARD; (* long menu_up; *)
  4006.                          menutree   : LONGCARD; (* long menutree; *)
  4007.                          desktree   : LONGCARD; (* long desktree; *)
  4008.                          desk_1stob : LONGCARD; (* long desktree_1stob; *)
  4009.                          dos_magic  : LONGCARD; (* long dos_magic; *)
  4010.                          max_windn  : LONGCARD; (* long maxwindn; *)
  4011.                          fsel       : ADDRESS;  (* int  ( **fsel) (char* path, char* name, int* button, char* title); *)
  4012.                          dummy      : LONGCARD; (* long dummy; *)
  4013.                      END;
  4014.     AESVARPTR   = POINTER TO magAESVARS;
  4015.     
  4016.     magXCookiePtr = POINTER TO RECORD
  4017.                                  config_status : LONGCARD;  (* long    config_status; *)
  4018.                                  dosvars       : ADDRESS;   (* DOSVARS *dosvars; *)
  4019.                                  aesvars       : AESVARPTR; (* AESVARS *aesvars; *)
  4020.                                END;
  4021.  
  4022. VAR magX_ptr : magXCookiePtr;
  4023.  
  4024. BEGIN
  4025.   iconifySupportEnabled := FALSE;
  4026.   InitQueue();                  (* Init Window Queue *)
  4027.   (* Init der anderen Variablen *)
  4028.   MagicAES.WindGet (0, MagicAES.WFWORKXYWH, deskSize); (* Gr”že des Desktops abfragen *)
  4029.   windows := NIL;
  4030.   control7:= ADR (VDIControl[7]);
  4031.   control9:= ADR (VDIControl[9]);
  4032.   (* Term-Proc anmelden *)
  4033.   mtAppl.InstallTermproc (windowTerm);
  4034.   (* globale Prozeduren initialisieren *)
  4035.   handleNewTop := handleNewTopProc(NIL);    (* Siehe Kommentar zu Typ *)
  4036.   handlePostEvent := handleEventProc(NIL);    (* Siehe Kommentar zu Typ *)
  4037.   handleGlobalKey := handleGlobalKeyProc (NIL);
  4038.   handleGlobalMess := handleMessProc (NIL);
  4039.   multiTOS := MagicAES.AESGlobal.apVersion >= $400;
  4040.   (* Cookie abfragen, ob Mag!X *)
  4041.   magIx := ~multiTOS & 
  4042.            MagicCookie.FindCookie (MagiXCookie, magX_ptr);
  4043.   IF magIx
  4044.   THEN
  4045.     magIxVer := magX_ptr^.aesvars^.version;
  4046.   END;
  4047.   MagicAES.hasAgi := MagicAES.hasAgi OR 
  4048.                      (magIx & (magIxVer >= $200));
  4049.   onlyOneTop := -1;
  4050.   iconHdl := NIL;
  4051.   allIconified := FALSE;
  4052.   globalMenu := NIL;
  4053.   disableCounter := 0;
  4054.   menuDisabled := FALSE;
  4055.   MagicPCKeyTrans := FALSE;
  4056. END WdwManager.
  4057.